[英]Producer consumer not giving desired result
我正在从java 文档学习线程同步。 我实现了一个著名的问题生产者-消费者问题。 但它没有按预期给出结果。 我在HERE 、 HERE 、 HERE 、 HERE 、 HERE和其他一些堆栈交换和非堆栈交换站点上搜索了很多关于这个问题,但无法解决我的问题。 这是我的代码:
获取设置项.java
public class GetSetItem {
private volatile boolean available = false;
private int item;
public synchronized void set(int item) {
while(available) {
try {
wait();
} catch (InterruptedException ie) {
System.err.println("Interrupted: " + ie.getMessage());
}
}
this.item = item;
available = true;
notifyAll();
}
public synchronized int get() {
while(!available) {
try {
wait();
} catch (InterruptedException ie) {
System.err.println("Interrupted: " + ie.getMessage());
}
}
available = false;
notifyAll();
return item;
}
}
消费者.java
public class Consumer implements Runnable {
private int number; // Just for show #1,#2 etc. For future use
private GetSetItem consumer;
public Consumer(GetSetItem item, int seq) {
consumer = item;
number = seq;
}
@Override
public void run() {
int value = -1;
for(int i = 0; i < 10; i++) {
value = consumer.get();
System.out.println("Consumer #" + number + " get: " + value);
}
}
}
生产者.java
public class Producer implements Runnable {
private GetSetItem producer;
private int number = 0;
public Producer(GetSetItem item, int seq) {
producer = item;
number = seq;
}
@Override
public void run() {
for(int i = 0; i < 10; i++) {
producer.set(i);
System.out.println("Producer #" + number + " Put: " + i);
}
}
}
ProducerConsumerMain.java
public class ProducerConsumerMain {
public static void main(String[] args) {
GetSetItem item = new GetSetItem();
Producer p = new Producer(item, 1);
Consumer c = new Consumer(item, 1);
new Thread(p).start();
new Thread(c).start();
}
}
输出是:
Consumer #1 get: 0
Producer #1 Put: 0
Producer #1 Put: 1
Consumer #1 get: 1
Producer #1 Put: 2
Consumer #1 get: 2
Producer #1 Put: 3
Consumer #1 get: 3
Producer #1 Put: 4
Producer #1 Put: 5
Consumer #1 get: 4
Consumer #1 get: 5
Producer #1 Put: 6
Producer #1 Put: 7
Consumer #1 get: 6
Consumer #1 get: 7
Consumer #1 get: 8
Producer #1 Put: 8
Producer #1 Put: 9
Consumer #1 get: 9
但是输出应该是生产者 - > 消费者格式。 这意味着消费者只有在产品可用且由生产者生产时才能消费它。 我也试过private boolean available = false
而不是private volatile boolean available = false;
但没有收到预期的输出。
所以请告诉我我做错了什么,我怎样才能成功地解决这个问题。
您的代码看起来不错,问题很可能是System.out
不是线程安全的。 您还需要同步println()
调用:
@Override
public void run() {
for (int i = 0; i < 10; i++) {
producer.set(i);
synchronized (System.out) {
System.out.println("Producer #" + number + " Put: " + i);
}
}
}
然后,输出将类似于:
Producer #1 Put: 0
Producer #1 Put: 1
Consumer #1 get: 0
Consumer #1 get: 1
Producer #1 Put: 2
Producer #1 Put: 3
Consumer #1 get: 2
Consumer #1 get: 3
Producer #1 Put: 4
Consumer #1 get: 4
Producer #1 Put: 5
Producer #1 Put: 6
Consumer #1 get: 5
Consumer #1 get: 6
Consumer #1 get: 7 <<<<
Producer #1 Put: 7 <<<<
Producer #1 Put: 8
Consumer #1 get: 8
Consumer #1 get: 9 <<<<
Producer #1 Put: 9 <<<<
您的线程仍有可能在get/set
和println
语句之间暂停,在这种情况下,它看起来好像您的消费者正在消费尚未生产的东西,就像我在上面的输出中指出的那样。 不过,这只是一个输出问题,您的代码运行良好,并完成了它应该做的事情。
我通过在GetSetItem
类的get()
和set()
方法中使用System.out.println(...)
语句并从相应的producer
和consumer
类中删除System.out.println(...)
解决了这个问题。 作为:
GetSetItem.java 的get() 方法
public synchronized void set(int item, int number) {
while(available) {
try {
wait();
} catch (InterruptedException ie) {
System.err.println("Interrupted: " + ie.getMessage());
}
}
this.item = item;
/* Putting this line here gives expected output because this
* statement is synchronized due to method synchronization.
*/
System.out.println("Producer #" + number + " Produced: " + item);
available = true;
notifyAll();
}
GetSetItem.java 的set() 方法
public synchronized int get(int number) {
while (!available) {
try {
wait();
} catch (InterruptedException ie) {
System.err.println("Interrupted: " + ie.getMessage());
}
}
/*
* Putting this line here gives expected output because this statement
* is synchronized due to method synchronization.
*/
System.out.println("Consumer #" + number + " Consumed: " + item);
available = false;
notifyAll();
return item;
}
编辑:输出:
Producer #1 Produced: 0
Consumer #1 Consumed: 0
Producer #1 Produced: 1
Consumer #1 Consumed: 1
Producer #1 Produced: 2
Consumer #1 Consumed: 2
Producer #1 Produced: 3
Consumer #1 Consumed: 3
Producer #1 Produced: 4
Consumer #1 Consumed: 4
Producer #1 Produced: 5
Consumer #1 Consumed: 5
Producer #1 Produced: 6
Consumer #1 Consumed: 6
Producer #1 Produced: 7
Consumer #1 Consumed: 7
Producer #1 Produced: 8
Consumer #1 Consumed: 8
Producer #1 Produced: 9
Consumer #1 Consumed: 9
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.