gpt4 book ai didi

java - 为什么我的notify()不起作用?

转载 作者:行者123 更新时间:2023-12-01 23:52:40 25 4
gpt4 key购买 nike

我的notifyAll()方法似乎都不起作用。露西应该等到鲍勃到达然后释放。鲍勃应该等待露西的确认然后释放。这些事情似乎都没有发生。

有人可以让我知道我做错了什么以及如何解决它。提前致谢。

编辑 - 我根据格雷的建议修改了我的代码。异常消失了,但 notify() 方法似乎仍然不起作用。

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我已经按照格雷的建议调整了我的代码。hasArrived 现在是不稳定的并且位于 playDates run 方法中。它在内部类 Boys run 方法中更改为 true。输出没有改变,问题似乎是一样的。还有进一步的建议吗?

更新的代码:

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);
}
}
}

最佳答案

您正在启动Girl初始化 bob 之前的线程字段,这样你就会得到一个 NPE。您应该初始化您的 bob字段之前 Girl并应该将其传递到该线程中。您的程序可能在某些情况下有效,但存在不可预测的竞争条件。如果线程启动得足够快,它可能会工作,但您应该初始化 bob 开始Girl之前线程。

你还有一些memory synchronization issues 。例如,尽管您正在 PlayDates.this 上同步,Boy Girl 时,类可能尚未初始化和同步。线程调用bob.hasArrived() 。每当在多个线程中访问一个字段时,您需要确保两个线程都看到正确同步的值。您可以通过设置hasArrived来确保这一点成为 AtomicBoolean或标记 hasArrived作为volatile .

编辑:

问题正在发生变化,所以我会尽力跟上。我建议不要设置 hasArrived是真实的Boy构造函数。我认为你应该做到 volatile并设置在 run()方法。您想要Girl线程启动,运行一下,然后看到 Boy不可用并且 wait() 。所以Boy线程应该稍后启动并设置 hasArrived成为true在它的run() sleep() 之后的方法.

关于java - 为什么我的notify()不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16123456/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com