Java等待/通知
我花了很长时间试图找出为什么这不起作用,但根本找不到答案。 我想做的是,让两个班级互相“交谈”。 基本上,我想让A做点什么,以及为B做什么(B也一样)Java等待/通知,java,notify,Java,Notify,我花了很长时间试图找出为什么这不起作用,但根本找不到答案。 我想做的是,让两个班级互相“交谈”。 基本上,我想让A做点什么,以及为B做什么(B也一样) 如果要等待线程完成,请尝试“加入”。java文档中有一个很好的例子: 因此,在您的情况下,如果您想在调用B上的start之前等待A完成 a.start(); a.join(); b.start(); 至少,这是我认为您要问的问题(您的问题似乎有点不清楚)。您的代码还有其他问题(见下文),但您遇到的问题是,由于在等待之前检查了条件,如B:
如果要等待线程完成,请尝试“加入”。java文档中有一个很好的例子: 因此,在您的情况下,如果您想在调用B上的start之前等待A完成
a.start();
a.join();
b.start();
至少,这是我认为您要问的问题(您的问题似乎有点不清楚)。您的代码还有其他问题(见下文),但您遇到的问题是,由于在等待之前检查了条件,如B
:
public void run() {
while(!t.aCanTalk) {
....
}
}
如果t.aCanTalk
为true,则run方法将简单地返回,线程死亡
(我最初对您的代码的误读说明如下:-)
也就是说,您应该真正地重新构造代码,因为如果您使用更多“打包”方法制作一个适当的监视器,那么代码就不那么容易出错,例如一个简单的rendez-vous示例:
class Test {
private boolean aCanTalk = true;
public synchronized waitA() {
while(!aCanTalk) {
wait();
}
}
public synchronized signalB() {
aCanTalk = false;
notifyAll();
}
public synchronized waitB() {
while(aCanTalk) {
wait();
}
}
public synchronized signalA() {
aCanTalk = true;
notifyAll();
}
}
并在线程中使用它,例如
以一种方式:
B:
public void run() {
while(true) {
t.waitB();
System.out.println("I am B");
t.signalA();
}
}
(InterruptedException
为简洁起见被忽略,它应该像在代码中一样被捕获或抛出)
wait
、notify
或notifyAll
的任何调用都应该用
try/catch子句(用于IllegalMonitorStateException
和
中断异常
)Boolean aCanTalk上同步代码>(注意大写字母B
!)
wait()
正在同步的对象的状态更改
notify()
,而只使用notifyAll()
(尽管在这种特殊情况下这并不重要,因为只有两个线程)wait
和notify
被引入以来,Java就得到了发展,而今天,对于大多数目的来说,您不必使用它们中的任何一个wait
或notify
,但仍实现相同的执行同步:
class ParaTest {
volatile boolean aCanTalk;
public static void main(String[] args) {
Test t = new Test();
t.t();
}
}
class Test {
volatile Boolean aCanTalk;
Thread a;
Thread b;
void t() {
aCanTalk = true;
a = new Thread(new A(this));
b = new Thread(new B(this));
a.start();
b.start();
try {
a.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class A implements Runnable {
Test t;
A(Test t) {
this.t = t;
}
public void run() {
System.out.println("I am A");
synchronized(t.aCanTalk) {
System.out.println("in synchronized (A)");
t.aCanTalk = false;
}
System.out.println("finished (A)");
}
}
class B implements Runnable {
Test t;
B(Test t) {
this.t = t;
}
public void run() {
System.out.println("I am B");
synchronized(t.aCanTalk) {
System.out.println("in synchronized (B)");
t.aCanTalk = true;
}
System.out.println("finished (B)");
}
}
当你说它不起作用时,它在做什么?它打印出“我是一个”并停止。我确信有人已经在写一个很长很全面的答案了。这里的问题是:(1)t.aCanTalk上存在数据竞争,这是一个非易失性变量;(2)a和B彼此不同步,因为它们在两个不同的锁上同步。仅当两个线程在同一对象上同步时,“同步”才起作用。尝试同步(t)(您必须将t标记为final,这在您的情况下似乎不是问题)@ortusolis告诉我
B.run
在启动时如果t.aCanTalk
为false将执行什么操作。如果您能在(false)时告诉,则
你自己解决问题是否已经走到了一半。我基本上试着让A做点什么,叫B,叫B做点什么,然后叫A等等。Sry,如果问题有点不明确,OP对wait和notify的使用是正确的。再读一遍a
等待b
并通知自己(a
),b
等待a
并通知自己(b
)。这不好,但也不是天生的问题。@SRobertz只是补充一下你的答案,这里没有必要使aCanTalk
易失性,因为你是从synchronized
方法中访问它的,这使得aCanTalk
更改对所有线程都立即可见。@Radiodef是的,我刚才看到了。因此,问题在于线程启动中存在一个争用条件:如果while循环中的条件为false,那么线程将简单地退出,而不会达到等待状态。意志edit@Magnamag它不是易变的,但我将其编辑为私有的,只是为了澄清它只应用于监视器操作。@SRobertz当然,这不是对您答案的更正,而是澄清,因为有人在某处评论过将aCanTalk
设置为volatile。第二点是不正确的:您必须在要等待的对象上进行同步。等待释放锁。
public void run() {
while(true) {
t.waitB();
System.out.println("I am B");
t.signalA();
}
}
class ParaTest {
volatile boolean aCanTalk;
public static void main(String[] args) {
Test t = new Test();
t.t();
}
}
class Test {
volatile Boolean aCanTalk;
Thread a;
Thread b;
void t() {
aCanTalk = true;
a = new Thread(new A(this));
b = new Thread(new B(this));
a.start();
b.start();
try {
a.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class A implements Runnable {
Test t;
A(Test t) {
this.t = t;
}
public void run() {
System.out.println("I am A");
synchronized(t.aCanTalk) {
System.out.println("in synchronized (A)");
t.aCanTalk = false;
}
System.out.println("finished (A)");
}
}
class B implements Runnable {
Test t;
B(Test t) {
this.t = t;
}
public void run() {
System.out.println("I am B");
synchronized(t.aCanTalk) {
System.out.println("in synchronized (B)");
t.aCanTalk = true;
}
System.out.println("finished (B)");
}
}