我正在尝试使用int itemHolder只有一个条目的消费者生产者问题。我不知道为什么消费者线程在放置项目时没有通知生产者线程。预期的行为是消费者线程等待生产者将项目放入itemHolder。 另一方面,当我在外部mutax对象上使用锁定时,它可以很好地工作。
public class ProducerConsumer {
public static void main(String... args) {
new ProducerConsumer().execute();
}
private volatile int itemHolder = -1; // -1 value represent that ItemHolder is empty
private void execute() {
final Thread producer = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i < 5; i++) {
synchronized (this){
while (itemHolder != -1){ // ItemHolder is full
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
itemHolder = i;
notify();
System.out.println(String.format("producer: ItemHolder has value, Consumer notified..."));
}
}
}
}, "Producer-thread");
final Thread consumer = new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (producer){
try {
while (itemHolder == -1){ // Don't consume if itemHolder don't have a value
producer.wait();
}
System.out.println(String.format("CONSUMER: consuming %s...", itemHolder));
itemHolder = -1; // re-initialize the itemHolder
producer.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}, "Consumer-thread");
consumer.start();
producer.start();
}
锁定外部互斥锁 这可以正常工作。
public class ProducerConsumerWithMutex {
public static void main(String... args) {
new ProducerConsumerWithMutex().execute();
}
private final String mutex = "";
private volatile int itemHolder = -1;
private void execute() {
final Thread producer = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i < 5; i++) {
synchronized (mutex){
while (itemHolder != -1){ // itemHolder is full
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
itemHolder = i;
System.out.println(String.format("producer: producing %s...", i));
mutex.notify();
System.out.println(String.format("producer: Consumer notified, itemHolder has item..."));
}
}
}
}, "Producer-thread");
final Thread consumer = new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (mutex){
try {
while (itemHolder == -1){
System.out.println("CONSUMER: itemHolder is empty, waiting...");
mutex.wait();
}
System.out.println(String.format("CONSUMER: consuming %s...", itemHolder));
itemHolder = -1;
mutex.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}, "Consumer-thread");
consumer.start();
producer.start();
}
答案 0 :(得分:4)
因为在第一个生成器中,您在this
上进行同步,这是Runnable
,而不是生成器本身。
所以你需要使用synchronized(producer)
代替,但它不会编译,因为producer
在该行上尚不可用。
或者你可以命名你的Runnable:
Runnable producerRunnable = ...; //synchronized on this
并在您的消费者中:
synchronized(producerRunnable) {...}
但是你使用单独的互斥锁的第二种方法是可取的,除了锁定""
是一个非常糟糕的主意,因为这是一个全局常量(空字符串在字符串池中)。你应该更喜欢这样的东西:
private final Object mutex = new Object();
答案 1 :(得分:1)
当两个线程都使用相同的对象/类锁时,等待通知工作。在您的情况下,用于等待/通知的锁是不同的,如下所述:
synchronized(producer) // lock on producer object
synchronized(this) // Runnable object.
答案 2 :(得分:0)
在supportig assylias之后'这里的回答是另一种选择。
private Object lock = new Object();
锁定
synchronized (lock){
lock.wait();
}
解锁
synchronized (lock){
lock.notify();
}