多线程 - Java wait() notify()循环打印A和B
PHP中文网
PHP中文网 2017-04-17 16:40:47
0
4
554
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();
                /*}*/
            }
        }
    }
}
PHP中文网
PHP中文网

认证0级讲师

全員に返信(4)
大家讲道理

リーリー

コードにコメントを追加し、i を 4 に減らして、分析しやすくします。一度実行して出力ログを確認すると、どこに問題があるかがわかります。
実際、問題は A が実行を終了し、B が待機状態にあるため、誰も通知しに来ないことです。A をもう一度ループするだけで済みます。

いいねを押す +0
迷茫

これは生産者と消費者の問題に非常に似ています。あなたの質問の中で wait が無限に続く唯一の状況は、 ThreadA または ThreadB のいずれかが実行を終了し、スレッド wait が実行を終了していない場合、そのスレッドが実行されているため、もう一方のスレッドはそれをウェイクアップできません。もう終わった。

いいねを押す +0
伊谢尔伦

スレッド A が最初に実行されます。B がまだ待機していない場合、この時点で通知は無効になり、A の通知は実行を終了します。このように書くロジックに何か問題があります

いいねを押す +0
阿神

明らかに ThreadB が最初に待機しますが、コードは最初に ThreadA を呼び出します。ThreadB を最初に実行するだけです

リーリー

注: 2 つの Thread は同時に実行されます。java は、最初に呼び出された Thread が最初に実行されることを保証しません。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!