所以我一直在使用Java中的简单等待/通知示例,由于某种原因,我无法让它正常运行。如果有人能够看到可能是什么问题,我将非常感激!
class producer implements Runnable {
StringBuffer sb;
producer() {
sb=new StringBuffer("");
}
public void run () {
synchronized(sb) {
for(int i = 0; i < 10; i++) {
try {
sb.append(i+" ");
System.out.println("Appending ... ");
} catch (Exception e) {}
}
sb.notify();
}
}
}
class consumer implements Runnable {
producer p;
consumer(producer pp) {
this.p = pp;
}
public void run() {
System.out.println("Rreached");
synchronized(p.sb) {
try {
p.sb.wait();
} catch (Exception e) {}
System.out.println(p.sb);
}
}
}
class Thread_Comunication {
public static void main (String [] args) {
producer p = new producer();
consumer c = new consumer(p);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
输出:
Appending ...
Rreached // randome Position
Appending ...
Appending ...
Appending ...
Appending ...
Appending ...
Appending ...
Appending ...
Appending ...
Appending ...
所以由于某种原因,线程t1
没有唤醒t2
或者我完全错过了其他内容?
答案 0 :(得分:3)
除非另一个线程在等待,否则Notify不会执行任何操作。您的代码完全取决于通知(需要条件变量的位置),并依赖于在生产者之前运行的消费者,以使其工作。
根据你的输出,生产者首先运行;它将在消费者有机会运行之前完整执行。 (对于消费者运行它需要获取生成器所持有的sb上的锁。)生产者调用notify但没有线程在等待,所以它没有效果。然后消费者等待并且没有通知,所以它无限期地挂起。
如果消费者首先运行,那么代码将正常终止。
避免编写依赖于一个线程发生在另一个线程之前的代码,因为您无法控制先执行的操作。当你等待时,你需要在一个测试条件的循环中进行。其中一个原因是,如果在线程开始等待之前设置了条件,则线程可以知道不要等待。
更改代码以使用条件:
import java.io.*;
class producer implements Runnable {
StringBuffer sb;
boolean done = false;
producer() {
sb=new StringBuffer("");
}
public void run () {
synchronized(sb) {
for(int i=0;i<10;i++) {
try {
sb.append(i+" ");
System.out.println("Appending ... ");
} catch (Exception e) {}
}
sb.notify();
done = true;
}
}
}
class consumer implements Runnable {
producer p;
consumer(producer pp) {
this.p=pp;
}
public void run() {
System.out.println("Rreached");
synchronized(p.sb) {
try {
while (!p.done) {
p.sb.wait();
}
} catch (Exception e) {}
System.out.println(p.sb);
}
}
}
public class Communication {
public static void main (String [] args) throws Exception {
producer p= new producer();
consumer c= new consumer(p);
Thread t1= new Thread(p);
Thread t2= new Thread(c);
t2.start();
t1.start();
}
}
答案 1 :(得分:1)
所以我一直在使用Java中的简单等待/通知示例,由于某种原因,我无法让它正常运行。
您的代码存在的问题是notify()
未被保留。如果producer
首先进入synchronized
阻止 ,那么consumer
将无法输入它并转到wait
,直到{{} 1}}退出循环并完成。由于所有producer
次调用都发生在notify
块的内,所以当synchronized
到达consumer
时,{{1}已完成,不再调用wait()
。这意味着producer
已挂起。
即使您首先启动notify
,您仍然会遇到可能导致consumer
首先进入其consumer
块的竞争条件 - 尤其如此,因为{ {1}}调用producer
需要时间。虽然不是&#34;修复&#34;,如果您在synchronized
来电之前使用consumer
放慢System.out.println()
的速度,您应该会看到它现在有效,因为{{1在 producer
将其锁定之前,}}到达Thread.sleep(100)
。
有几种方法可以正确解决这个问题。通常我们使用wait / notify 和另一个synchronized
应检查的变量。在您的情况下,这可能是consumer
变量本身,因为它受到保护。所以wait()
可以做类似的事情:
producer