Java wait() notify()循环打印A和B

发布于 2022-09-02 00:15:34 字数 3227 浏览 12 评论 0

public class Test {
    
    public static Object object = new Object();
    public static boolean printA = true;
    
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.start();
        
        ThreadB threadB = new ThreadB();
        threadB.start();
    }
}
 
class ThreadA extends Thread {
    
    @Override
    public void run() {
        for(int i = 0; i < 10; i++) {
            synchronized (Test.object) {
                if(!Test.printA) {
                    try {
                        Test.object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("A");
                    Test.printA = false;
                    Test.object.notify();
                }
            }
        }
    }
}

class ThreadB extends Thread {
    
    @Override
    public void run() {
        for(int i = 0; i < 10; i++) {
            synchronized (Test.object) {
                if(Test.printA) {
                    try {
                        Test.object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("B");
                    Test.printA = true;
                    Test.object.notify();
                }
            }
        }
    }
}

运行以上代码,为什么会一直不结束无限wait下去?

------------------ 分割线,以下是正确的写法 -------------------

实际上线程中不应该有else,把else注释掉就正确了。 如果加上else后,该线程会在wait后不再notify,导致另一个线程无限wait。

public class Test {
    
    public static Object object = new Object();
    public static boolean printA = true;
    
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.start();
        
        ThreadB threadB = new ThreadB();
        threadB.start();
    }
}
 
class ThreadA extends Thread {
    
    @Override
    public void run() {
        for(int i = 0; i < 10; i++) {
            synchronized (Test.object) {
                if(!Test.printA) {
                    try {
                        Test.object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }/* else {*/
                    System.out.println("A");
                    Test.printA = false;
                    Test.object.notify();
                /*}*/
            }
        }
    }
}

class ThreadB extends Thread {
    
    @Override
    public void run() {
        for(int i = 0; i < 10; i++) {
            synchronized (Test.object) {
                if(Test.printA) {
                    try {
                        Test.object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }/* else { */
                    System.out.println("B");
                    Test.printA = true;
                    Test.object.notify();
                /*}*/
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

东京女 2022-09-09 00:15:34
public class Test {

    public static Object object = new Object();
    public static boolean printA = true;

    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.setName("Thread-A");
        threadA.start();

        ThreadB threadB = new ThreadB();
        threadB.setName("Thread-B");
        threadB.start();
    }
}

class ThreadA extends Thread {
    @Override
    public void run() {
        System.out.println(this.getName() + ":start...");
        for (int i = 0; i < 4; i++) {
            System.out.println(this.getName() + ":i=" + i + "...");
            synchronized (Test.object) {
                System.out.println(this.getName() + ":i=" + i + " got lock...");
                if (!Test.printA) {
                    try {
                        System.out.println(this.getName() + ":i=" + i + " prepare to wait...");
                        Test.object.wait();
                        System.out.println(this.getName() + ":i=" + i + " wait over...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println(this.getName() + ":i=" + i + " print A...");
                    System.out.println("A");
                    Test.printA = false;
                    System.out.println(this.getName() + ":i=" + i + " prepare to notify...");
                    Test.object.notify();
                    System.out.println(this.getName() + ":i=" + i + " notify over...");
                }
            }
        }
    }
}

class ThreadB extends Thread {
    @Override
    public void run() {
        System.out.println(this.getName() + ":start...");
        for (int i = 0; i < 4; i++) {
            System.out.println(this.getName() + ":i=" + i + "...");
            synchronized (Test.object) {
                System.out.println(this.getName() + ":i=" + i + " got lock...");
                if (Test.printA) {
                    try {
                        System.out.println(this.getName() + ":i=" + i + " prepare to wait...");
                        Test.object.wait();
                        System.out.println(this.getName() + ":i=" + i + " wait over...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println(this.getName() + ":i=" + i + " print B...");
                    System.out.println("B");
                    Test.printA = true;
                    System.out.println(this.getName() + ":i=" + i + " prepare to notify...");
                    Test.object.notify();
                    System.out.println(this.getName() + ":i=" + i + " notify over...");
                }
            }
        }
    }
}

帮你的代码加了点注释,同时把i缩小到4,这样好分析点。你执行一遍然后看看输出的日志你就知道问题在哪了。
其实问题就是A执行完了,B正好处于wait状态,以至于没有人来notify他,你可以直接给A多循环一次即可。

清晨说晚安 2022-09-09 00:15:34

这个和生产者消费者的问题很像。你题目中无限wait下去唯一的情况是:当ThreadAThreadB有一方已执行完,未执行完的线程wait之后,另一线程并不能唤醒它,因为那个线程已跑完了。

十六岁半 2022-09-09 00:15:34

A线程先跑,如果B还没有wait的时候,A已经notify了,这时这个notify就没有效果,等B开始wait了,A的notify已经跑完了,根本永远得不到通知,你这么写逻辑是有问题的

我们的影子 2022-09-09 00:15:34

很明显ThreadB先wait,但代码却ThreadA先调用.... 只要让ThreadB先执行就可以了

ThreadB threadB = new ThreadB();
threadB.start();
        
Thread.sleep(10);
        
ThreadA threadA = new ThreadA();
threadA.start();

注意:两个Thread同时执行,java并不能能保证先调用的Thread先执行。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文