我是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");
}
}
}
}
我正在为生产者和消费者创建单独的线程。生产者线程仅在开始时被调用,之后再也不会执行。
我尝试了两种选择来解决此问题。首先,我将同步块之外的条件放在下面,
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();
}
}
}
}
两者都很好。使用哪种合适的解决方案?我仍然无法弄清楚为什么我所讨论的代码无法正常工作。
答案 0 :(得分:3)
我仍然无法弄清楚为什么我所讨论的代码无法正常工作
wait()
中的producer()
释放监视器,允许consumer()
进入其synchronized
块。然后wait()
中的producer()
开始等待,直到consumer()
调用notify()
并释放监视器(即退出其synchronized
块)。您永远不会退出synchronized
中的consumer()
,因此wait()
中的producer()
会永远被阻止
答案 1 :(得分:1)
我仍然无法弄清楚为什么我所讨论的代码不是 工作正常
我们已设法解决了您的代码,并附在固定的代码段下方。
我为ProducerConsumerWorld引入了一个名为isConsumed的布尔实例变量。这样做的本质是,在Producer Thread产生之后,他将isConsumed的状态更新为false,因为他产生了尚未消费的东西。此后,生产者通知消费者线程,生产者已经完成生产。接下来,它在ProducerConsumerWorld上调用wait(),从而释放Producer对ProducerConsumerWorld的锁定。然后,它等待ProducerConsumerWorld上的锁定。
与此同时,Consumer Thead获得了ProducerConsumerWorld上的锁,这使它可以进入Consumer方法,在此方法中检查是否还有待消费的农产品。如果是这样,它将使用isConsumed变量并将其更新为true,并通知生产已被消耗。然后,消费者通过调用wait()释放对ProducerConsumerWorld的锁定,并在Producer消费后等待重新获取对ProducerConsumerWorld的锁定。
注意:
在线程从同步块中移出或调用wait()从而释放锁之前,调用notify()不会释放锁。
来源: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();
}
}
}
}
这给了我类似
的输出