问题
I am trying to learn threads and hence I wrote a sample producer consumer problem wherein the producer produces numbers from 1 to 10 and the consumer has to display them. But only the consumer displays number 1 and stops.
As I said the program is not well written and might be absurd but still I want to figure out the reason why all the numbers from 1 to 10 are not printed as I will remembr best when I code rather than from examples.
I am using two varibales to track the completion of the Producres or consumers activity so that I can perform the other.
/getStatus(Consumer C) passing consumer reference so that producer gets a refrnce to consumer .. and it can be used to know status of consumer ..thats it ../
import java.lang.Math;
public class Hello{
public static void main(String args[]) {
System.out.println("---1");
new Consumer().start();
}
}
class Producer extends Thread{
public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;
public void run(){
System.out.println("---4");
synchronized(this){
do{
System.out.println("---6");
produce = produce+1;
producerStatus = true;
notify();
consumerObj.consumerStatus = false;
System.out.println("---9");
count = count+1;
}while(count<=10 && consumerObj.getStatus());
}
}
public int getItem(){
return produce;
}
public boolean getStatus(Consumer c){
consumerObj = c;
return producerStatus;
}
}
class Consumer extends Thread{
boolean consumerStatus = false;
int count =0;
public void run(){
System.out.println("---2");
Producer p = new Producer();
p.getStatus(this);
p.start();
try{
System.out.println("---3");
synchronized(p){
System.out.println("---5");
p.wait();
System.out.println("---8");
}
}
catch(Exception e){
System.out.println("exception");
}
synchronized(p){
try{
while(p.getStatus(this) && count<=9 ){
System.out.println("---7");
int consume = p.getItem();
System.out.println("the produced item is ----->"+consume);
count = count+1;
p.producerStatus = false;
consumerStatus = true;
p.wait();
System.out.println("---10");
}
}
catch(Exception e){
System.out.println("exception");
}
}
}
public boolean getStatus(){
return consumerStatus;
}
}
Output :
---1
---2
---3
---5
---4
---6
---9
---8
---7
the produced item is ----->1
---10
After inputs from .. Suraj .. Now the program is working fine .. see below ..
import java.lang.Math; public class Hello{
public static void main(String args[]) {
System.out.println("---1");
new Consumer().start();
}
}
class Producer extends Thread{
public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;
public void run(){
System.out.println("---4");
do{
if(consumerObj.getStatus()){
System.out.println("---6");
produce = produce+1;
System.out.println("---9 -- >produce is -->"+produce);
producerStatus = true;
synchronized(this){
notify();
System.out.println("---6.111");
}
consumerObj.consumerStatus = false;
count = count+1;
}
}while(count<=10);
}
public int getItem(){
return produce;
}
public boolean getStatus(Consumer c){
consumerObj = c;
return producerStatus;
}
}
class Consumer extends Thread{
boolean consumerStatus = true;
int count =1;
public void run(){
System.out.println("---2");
Producer p = new Producer();
p.getStatus(this);
p.start();//can a thread1 wait on an thread2 before the thread2 hass tarted and in this case wll notify on the scnd thread reaally notify therad1 ..
try{
System.out.println("---3");
synchronized(p){
System.out.println("---5");
p.wait();
System.out.println("---8");
}
}
catch(Exception e){
System.out.println("exception");
}
try{
while(count<=10 ){
System.out.println("---7");
int consume = p.getItem();
System.out.println("the produced item is ----->"+consume);
count = count+1;
p.producerStatus = false;
consumerStatus = true;
synchronized(p){
p.wait();
System.out.println("---10");
}
}
}
catch(Exception e){
System.out.println("exception");
}
}
public boolean getStatus(){
return consumerStatus;
}
}
回答1:
OK. The program is wrong.
- The consumer thread comes and waits for lock.
- The first iteration in the loop of producer will call notify but doesent release the lock as the while loop is inside synchronized block. It will iterarte 10 times without releasing the lock and ends up calling notify 10 times continuously.
- But the Consumer only gets to wakeup once and the second time the consumer calls wait() it keeps on waiting as there is noone to call notify now(as the Producer's all 10 iterations are over)
So the problem is Consumer thread is wating but there's no-one to notify it, as the Producer finished its all 10 iterations in 1 shot.
回答2:
in Producer, you set
consumerObj.consumerStatus = false;
and check this value in loop condition immediately. Loops end after 1 cycle. After
count = count+1;
you should wait (for "consumption").
try{
this.wait();
} catch (Exception e) {
e.printStackTrace();
}
The same problem in Consumer. Last thing in the loop should be
p.wait();
回答3:
You should use BlockingQueues. see http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml.
The above implementation is ineffecient and it forces all consurmers to block. with multiple queues you can prevent all consumers from blocking. You can find examples on google. Java.util.concurrent Use it , it is there for a reason.
来源:https://stackoverflow.com/questions/6177247/java-threads-producer-consumer-algorithm-not-working-properly