[英]Proper use of wait and notify methods in Java threading
我是 Java 多线程的新手。 我使用 wait 和 notify 创建了简单的生产者-消费者模式,但我的生产者在开始时只被调用一次。
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorldp = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
}
}
}
}
我正在为生产者和消费者创建单独的线程。 生产者线程仅在开始时被调用,然后永远不会被执行。
我尝试了两种选择来克服这个问题。 首先我把 while 条件放在同步块之外的第二个下面给出。
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
notify();
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
wait();
}
}
}
}
两者都很好用。 使用哪一种合适的解决方案? 我仍然无法弄清楚为什么我提出的代码不能正常工作。
我仍然无法弄清楚为什么我提出的代码不能正常工作
producer()
的wait()
释放允许consumer()
进入其synchronized
块的监视器。 然后producer()
的wait()
开始等待,直到consumer()
调用notify()
并释放监视器(即退出其synchronized
块)。 你永远不会在consumer()
退出synchronized
,因此producer()
的wait()
被永远阻塞
我仍然无法弄清楚为什么我提出的代码不能正常工作
我已设法修复您的代码,并附在固定代码片段下方。
我为 ProducerConsumerWorld 引入了一个名为 isConsumed 的布尔实例变量。 在这样做时,本质上发生的是在 Producer Thread 产生之后,他将 isConsumed 的状态更新为 false,因为他已经产生了一些尚未被消费的东西。 之后,生产者通知消费者线程,生产者已经完成生产。 接下来,它调用 ProducerConsumerWorld 上的 wait() 来释放 Producer 对 ProducerConsumerWorld 的锁定。 然后,它等待 ProducerConsumerWorld 上的锁定。
同时,Consumer Thead 获得了 ProducerConsumerWorld 的锁,这允许它进入消费者方法,在那里它检查是否有尚未消费的产品。 如果是这样,它会消耗并将 isConsumed 变量更新为 true,并通知产品已被消耗。 然后消费者通过调用wait()继续释放其在ProducerConsumerWorld上的锁,并在Producer消费后等待重新获取ProducerConsumerWorld上的锁。
笔记:
调用notify() 不会释放锁,直到线程移出同步块,或者调用wait(),从而释放锁。
来源:Oracle 的 OCA/OCP Java SE 7 学习指南第 760 页
代码:
import java.util.Scanner;
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorld p = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class ProducerConsumerWorld{
boolean consumed = false;
public void producer() throws InterruptedException{
System.out.println("Producer thread started running");
synchronized (this) {
while(this.consumed == true){ // Consumer has consumed and is waiting for produce
System.out.println("Resumed Producing");
this.consumed = false;
notify();
wait();
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(this.consumed == false){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
this.consumed = true;
System.out.println("consumed all");
notify();
wait();
}
}
}
}
这给了我一个输出,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.