天天看點

java:為什麼要總是使用對象的notifyAll而不使用notify?

最佳實踐:總是使用notifyAll而不使用notify

示例代碼:交替列印0和1的程式

package com.example.app;

import java.util.Date;

public class MyCounter2 {
    private int counter;

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }

    public synchronized void increase(){
        String name=Thread.currentThread().getName();
        System.out.println(System.currentTimeMillis()+" in thread: "+name+ " "+this.getCounter());
        while(this.getCounter()>0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.counter++;
        System.out.println(System.currentTimeMillis()+" "+name+" "+this.counter);
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.notify();
    }

    public synchronized void decrease(){
        String name=Thread.currentThread().getName();
        System.out.println(System.currentTimeMillis()+" in thread: "+name+ " "+this.getCounter());
        while(this.getCounter()<1){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.counter--;
        System.out.println(System.currentTimeMillis()+" "+name+" "+this.counter);
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.notify();
    }
}
      
package com.example.app;

public class NotifyTest2 {
    private static MyCounter2 myCounter = new MyCounter2();
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new ThreadA(myCounter);

       Thread t2= new ThreadB(myCounter);

       Thread t3=new ThreadC(myCounter);
       Thread t4 = new ThreadD(myCounter);

        t1.start();
        t2.start();
        t3.start();
        t4.start();

        t1.join();
        t2.join();
        t3.join();
        t4.join();

    }
}

class ThreadA extends Thread{
    private MyCounter2 myCounter;
    public ThreadA(MyCounter2 myCounter){
        this.myCounter=myCounter;
        setName("thread-A");
    }
    @Override
   public void run(){
        while(true){
            myCounter.increase();
        }
    }
}

class ThreadB extends Thread{
    private MyCounter2 myCounter;
    public ThreadB(MyCounter2 myCounter){
        this.myCounter=myCounter;
        setName("thread-B");
    }
    @Override
    public void run(){
        while(true){
            myCounter.decrease();
        }
    }
}



class ThreadC extends Thread{
    private MyCounter2 myCounter;
    public ThreadC(MyCounter2 myCounter){
        this.myCounter=myCounter;
        setName("thread-C");
    }
    @Override
    public void run(){
        while(true){
            myCounter.increase();
        }
    }
}

class ThreadD extends Thread{
    private MyCounter2 myCounter;
    public ThreadD(MyCounter2 myCounter){
        this.myCounter=myCounter;
        setName("thread-D");
    }
    @Override
    public void run(){
        while(true){
            myCounter.decrease();
        }
    }
}
      

一次執行結果及執行時序圖分析

java:為什麼要總是使用對象的notifyAll而不使用notify?