java 中线程的等待和通知顺序
sequence of wait and notify of threads in java
我写了一个producer/consumer程序如下。
package com.myjava.concurrency.basics.waitnotify;
import java.util.PriorityQueue;
import java.util.Queue;
public class SharedObject {
private Queue<String> dataObject;
private final Object objLock = new Object();
public SharedObject() {
dataObject = new PriorityQueue<String>(1);
}
public void writeData(String data) {
synchronized (objLock) {
while (!dataObject.isEmpty()) {
System.out.println("Producer:Waiting");
try {
objLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dataObject.offer(data);
System.out.println(String.format("%s : %s",
Thread.currentThread().getName(), data));
objLock.notify();
}
}
public String readData() {
String result = null;
synchronized (objLock) {
while (dataObject.isEmpty()) {
System.out.println("Consumer:Waiting");
try {
objLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = dataObject.poll();
System.out.println(String.format("%s : %s",
Thread.currentThread().getName(), result));
objLock.notify();
}
return result;
}
}
package com.myjava.concurrency.basics.waitnotify;
import java.util.Arrays;
import java.util.List;
public class TestWaitNotify {
public static void main(String[] args) {
SharedObject sharedObject = new SharedObject();
List<String> fruitsList = Arrays.asList("Apple", "Banana", "Orange");
int listSize = fruitsList.size();
Thread producer = new Thread(() -> {
System.out.println("producer thread started");
fruitsList.forEach(p -> {
sharedObject.writeData(p);
});
}, "producer");
Thread consumer = new Thread(() -> {
System.out.println("consumer thread started");
for (int i = 0; i < listSize; i++) {
sharedObject.readData();
}
}, "consumer");
consumer.start();
producer.start();
}
}
我得到了如下输出:
producer thread started
consumer thread started
Consumer:Waiting
producer : Apple
Producer:Waiting
consumer : Apple
Consumer:Waiting
producer : Banana
Producer:Waiting
consumer : Banana
Consumer:Waiting
producer : Orange
consumer : Orange
这是我的问题:
我希望这个程序有以下顺序:
producer thread started
consumer thread started
Consumer:Waiting // assuming consumer thread begins first
producer : Apple
consumer : Apple
producer : Banana
consumer : Banana
producer : Orange
consumer : Orange
只有消费者线程只能进入等待模式一次。第一次通知后,线程不要进入while循环,因为当生产者线程有对象锁时,消费者应该等待锁,当消费者释放锁时,生产者应该获得锁。
感谢任何帮助。
Object.notify() 将唤醒等待锁的线程,但它不一定优先获取下一个锁,javadoc 标识了此行为:
The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
可能发生的情况是刚刚放弃锁的线程立即在您期望的线程前面再次获取锁。如果您在通知后休眠(但 而不是 在同步块中),您可能会看到您期望的输出。在这种情况下,您强制该线程有效地屈服于已通知的其他线程。
检查本教程可能会对您有所帮助,它看起来与您的问题非常相似,即使它与您的示例的唯一区别是方法符号,顺便说一句,它们有 synchronized
关键字。
https://www.tutorialspoint.com/javaexamples/thread_procon.htm
这里:
while (dataObject.isEmpty()) {
System.out.println("Consumer:Waiting");
消费者消费一个条目。但与此同时,队列已锁定,因此在此期间无法添加任何内容。
所以生产者必须等待消费者消费,然后消费者必须等待生产者放入新的东西。
因此有以下假设
Only consumer thread should enter in wait mode only once.
错了。
我写了一个producer/consumer程序如下。
package com.myjava.concurrency.basics.waitnotify;
import java.util.PriorityQueue;
import java.util.Queue;
public class SharedObject {
private Queue<String> dataObject;
private final Object objLock = new Object();
public SharedObject() {
dataObject = new PriorityQueue<String>(1);
}
public void writeData(String data) {
synchronized (objLock) {
while (!dataObject.isEmpty()) {
System.out.println("Producer:Waiting");
try {
objLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
dataObject.offer(data);
System.out.println(String.format("%s : %s",
Thread.currentThread().getName(), data));
objLock.notify();
}
}
public String readData() {
String result = null;
synchronized (objLock) {
while (dataObject.isEmpty()) {
System.out.println("Consumer:Waiting");
try {
objLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = dataObject.poll();
System.out.println(String.format("%s : %s",
Thread.currentThread().getName(), result));
objLock.notify();
}
return result;
}
}
package com.myjava.concurrency.basics.waitnotify;
import java.util.Arrays;
import java.util.List;
public class TestWaitNotify {
public static void main(String[] args) {
SharedObject sharedObject = new SharedObject();
List<String> fruitsList = Arrays.asList("Apple", "Banana", "Orange");
int listSize = fruitsList.size();
Thread producer = new Thread(() -> {
System.out.println("producer thread started");
fruitsList.forEach(p -> {
sharedObject.writeData(p);
});
}, "producer");
Thread consumer = new Thread(() -> {
System.out.println("consumer thread started");
for (int i = 0; i < listSize; i++) {
sharedObject.readData();
}
}, "consumer");
consumer.start();
producer.start();
}
}
我得到了如下输出:
producer thread started
consumer thread started
Consumer:Waiting
producer : Apple
Producer:Waiting
consumer : Apple
Consumer:Waiting
producer : Banana
Producer:Waiting
consumer : Banana
Consumer:Waiting
producer : Orange
consumer : Orange
这是我的问题:
我希望这个程序有以下顺序:
producer thread started
consumer thread started
Consumer:Waiting // assuming consumer thread begins first
producer : Apple
consumer : Apple
producer : Banana
consumer : Banana
producer : Orange
consumer : Orange
只有消费者线程只能进入等待模式一次。第一次通知后,线程不要进入while循环,因为当生产者线程有对象锁时,消费者应该等待锁,当消费者释放锁时,生产者应该获得锁。
感谢任何帮助。
Object.notify() 将唤醒等待锁的线程,但它不一定优先获取下一个锁,javadoc 标识了此行为:
The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
可能发生的情况是刚刚放弃锁的线程立即在您期望的线程前面再次获取锁。如果您在通知后休眠(但 而不是 在同步块中),您可能会看到您期望的输出。在这种情况下,您强制该线程有效地屈服于已通知的其他线程。
检查本教程可能会对您有所帮助,它看起来与您的问题非常相似,即使它与您的示例的唯一区别是方法符号,顺便说一句,它们有 synchronized
关键字。
https://www.tutorialspoint.com/javaexamples/thread_procon.htm
这里:
while (dataObject.isEmpty()) {
System.out.println("Consumer:Waiting");
消费者消费一个条目。但与此同时,队列已锁定,因此在此期间无法添加任何内容。
所以生产者必须等待消费者消费,然后消费者必须等待生产者放入新的东西。
因此有以下假设
Only consumer thread should enter in wait mode only once.
错了。