Java 为什么我的notify()不起作用?
我的notifyAll()方法似乎都不起作用。 露西应该等到鲍勃来了再放。 Bob应该等待Lucy的确认,然后释放。 这两件事似乎都没有发生 有人能让我知道我做错了什么,以及我如何着手解决它吗。 提前谢谢 编辑-我使用灰色建议修改了代码。 异常消失,但notify()方法似乎仍不起作用Java 为什么我的notify()不起作用?,java,multithreading,wait,synchronized,notify,Java,Multithreading,Wait,Synchronized,Notify,我的notifyAll()方法似乎都不起作用。 露西应该等到鲍勃来了再放。 Bob应该等待Lucy的确认,然后释放。 这两件事似乎都没有发生 有人能让我知道我做错了什么,以及我如何着手解决它吗。 提前谢谢 编辑-我使用灰色建议修改了代码。 异常消失,但notify()方法似乎仍不起作用 import java.util.logging.Level; import java.util.logging.Logger; public class PlayDates { Thread lucy
import java.util.logging.Level;
import java.util.logging.Logger;
public class PlayDates {
Thread lucyThread;
Girl lucy;
Thread bobThread;
Boy bob;
public static void main(String[] args) {
PlayDates playDates = new PlayDates();
playDates.run();
}
public void run() {
lucy = new Girl();
lucyThread = new Thread(lucy);
bob = new Boy();
bobThread = new Thread(bob);
lucyThread.start();
threadSleep(500);
bobThread.start();
}
public class Girl implements Runnable {
@Override
public void run() {
synchronized(PlayDates.this){
System.out.println("Girl synchronized hit");
if(!bob.hasArrived()) { // Doesnt seem to get past here?
System.out.println("Lucy has fallen asleep waiting for Bob");
try {
PlayDates.this.wait(); // Wait for Bob
System.out.println("Lucy has woken up");
PlayDates.this.notifyAll(); // Acknowledge Bobs arrival
} catch (InterruptedException ex) {
Logger.getLogger(PlayDates.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public class Boy implements Runnable {
private boolean hasArrived;
@Override
public void run() {
synchronized(PlayDates.this){
System.out.println("Bob has arrived to play");
PlayDates.this.notifyAll();
try {
PlayDates.this.wait(); // Wait for Lucy to acknowledge Bobs arrival
} catch (InterruptedException ex) {
Logger.getLogger(PlayDates.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Bob and Lucy are playing");
}
}
public Boy() {
hasArrived = true;
}
public boolean hasArrived() {
return hasArrived;
}
}
public void threadSleep(int milli) {
try {
Thread.sleep(milli);
} catch (InterruptedException ex) {
Logger.getLogger(PlayDates.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
电流输出
Girl synchronized hit
Bob has arrived to play
编辑2 我已经按照格雷斯的建议修改了代码。 HasArrimit现在是易变的,并且在playDates运行方法中。 在班内男孩跑步方法中,它变为真。 输出没有改变,问题似乎是相同的。 还有什么建议吗 更新代码:
import java.util.logging.Level;
import java.util.logging.Logger;
public class PlayDates {
Thread lucyThread;
Girl lucy;
Thread bobThread;
Boy bob;
volatile boolean hasArrived;
public static void main(String[] args) {
PlayDates playDates = new PlayDates();
playDates.run();
}
public void run() {
hasArrived = false;
lucy = new Girl();
lucyThread = new Thread(lucy);
bob = new Boy();
bobThread = new Thread(bob);
lucyThread.start();
threadSleep(500);
bobThread.start();
}
public class Girl implements Runnable {
@Override
public void run() {
synchronized(PlayDates.this){
System.out.println("Girl synchronized hit");
if(hasArrived) { // Doesnt seem to get past here?
System.out.println("Lucy has fallen asleep waiting for Bob");
try {
PlayDates.this.wait(); // Wait for Bob
System.out.println("Lucy has woken up");
PlayDates.this.notifyAll(); // Acknowledge Bobs arrival
} catch (InterruptedException ex) {
Logger.getLogger(PlayDates.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
public class Boy implements Runnable {
@Override
public void run() {
threadSleep(1000);
synchronized(PlayDates.this){
System.out.println("Bob has arrived to play");
hasArrived = true;
PlayDates.this.notifyAll();
try {
PlayDates.this.wait(); // Wait for Lucy to acknowledge Bobs arrival
} catch (InterruptedException ex) {
Logger.getLogger(PlayDates.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Bob and Lucy are playing");
}
}
}
public void threadSleep(int milli) {
try {
Thread.sleep(milli);
} catch (InterruptedException ex) {
Logger.getLogger(PlayDates.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
在初始化
bob
字段之前,您正在启动Girl
线程,以便获得NPE。您应该在Girl
之前初始化bob
字段,并将其传递到该线程中。您的程序可能在某些情况下工作,但存在不可预测的竞争条件。如果线程启动速度足够快,它可能会工作,但您应该在启动Girl
线程之前初始化bob
你也有一些。例如,尽管您正在playdate上同步。这
,但当Girl
线程调用bob.hasarimited()
时,Boy
类可能尚未初始化和同步。每当在多个线程中访问一个字段时,您需要确保两个线程都看到了正确同步的值。您可以通过将hasarimited
设置为AtomicBoolean
或将hasarimited
标记为volatile
来确保这一点
编辑:
问题在变,所以我会努力跟上。我建议不要在
Boy
构造函数中将hasarimited
设置为true。我认为应该将其设置为volatile,并在run()
方法中设置。您希望启动Girl
线程,运行一点,然后看到Boy
不可用,并且wait()
。因此,Boy
线程应该稍后启动,并在sleep()之后的run()
方法中将hasarimited
设置为true
,然后在初始化bob
字段之前启动Girl
线程,这样您将获得NPE。您应该在Girl
之前初始化bob
字段,并将其传递到该线程中。您的程序可能在某些情况下工作,但存在不可预测的竞争条件。如果线程启动速度足够快,它可能会工作,但您应该在启动Girl
线程之前初始化bob
你也有一些。例如,尽管您正在playdate上同步。这
,但当Girl
线程调用bob.hasarimited()
时,Boy
类可能尚未初始化和同步。每当在多个线程中访问一个字段时,您需要确保两个线程都看到了正确同步的值。您可以通过将hasarimited
设置为AtomicBoolean
或将hasarimited
标记为volatile
来确保这一点
编辑:
问题在变,所以我会努力跟上。我建议不要在Boy
构造函数中将hasarimited
设置为true。我认为应该将其设置为volatile,并在run()
方法中设置。您希望启动Girl
线程,运行一点,然后看到Boy
不可用,并且wait()
。因此,Boy
线程应该稍后启动,并在sleep()之后的run()
方法中将hasarimited
设置为true
,我希望我的Girl字段等待Bob字段。我已经使用您的建议修改了我的代码,这样NPE就不会再被抛出,但notify方法似乎仍然不起作用。您只需要在调用start()之前构造Bob
类
在你的Girl
thread@James上。我的回答的第二部分可能有助于解决你的同步问题@James。谢谢你的建议。我已尝试按照您的建议编辑代码。不幸的是,错误没有改变。我错过了什么?你不是说!已经到了
?您需要在代码中跟踪它,或者学习如何使用调试器。我想让我的女朋友菲尔德等鲍勃·菲尔德。我已经使用您的建议修改了我的代码,这样NPE就不会再被抛出,但notify方法似乎仍然不起作用。您只需要在调用start()之前构造Bob
类
在你的Girl
thread@James上。我的回答的第二部分可能有助于解决你的同步问题@James。谢谢你的建议。我已尝试按照您的建议编辑代码。不幸的是,错误没有改变。我错过了什么?你不是说!已经到了
?您需要在代码中跟踪它,或者学习如何使用调试器。如果你一直在编辑这个问题,很难回答@James。它使我们的答案无效。“这不应该是一个论坛。”格雷,对不起,我是新来的。将来,我应该用修改后的代码问一个新问题吗?你可以编辑你的答案,并在末尾添加一个新的部分。@Gray好的,这就是我将来要做的。对不起,伙计。我已经用附加信息编辑了我的答案。如果你一直在编辑它,很难回答这个问题@James。它使我们的答案无效。“这不应该是一个论坛。”格雷,对不起,我是新来的。将来,我是否应该就修订后的守则提出一个新问题