1. 程式人生 > >java多執行緒中等待/通知機制

java多執行緒中等待/通知機制

一個執行緒做了修改物件值(或其他)操作,另一個執行緒感知到了變化,然後進行相應操作,整個過程開始於一個執行緒,最終執行又是另外一個執行緒。前者是生產者,後者是消費者,這種模式隔離了“做什麼”和“怎麼做”,實現了業務上的解耦。

其具體實現方式是執行緒A呼叫了物件O的wait()方法進入等待狀態,另一個執行緒B呼叫物件B的notify() or notifyAll()方法,執行緒A收到通知後從物件O的wait()方法返回,進而執行後續操作 。其邏輯流程如下:

thread1 得到object1 的 monitor, 呼叫 object1.wait() 
  - 釋放object1 的 monitor, thread1
wait; thread2 得到 object1 的 monitor, 呼叫 object1.notify() - 啟用thread1, 釋放object1 的 monitor; thread1 得到 object1 的 monitor, 從object1.wait()返回, thread1接著執行.
演示demo如下:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class WaitNotify {
    static boolean flag = true;
    static Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread waitThread = new Thread(new Wait(), "WaitThread");
        waitThread.start();
        TimeUnit.SECONDS.sleep(1);

        Thread notifyThread = new Thread(new Notify(), "NotifyThread");
        notifyThread.start();
    }

    static class Wait implements Runnable {
        @Override
        public void run() {
            synchronized (lock) {
                while (flag) {
                    try {
                        System.out.println(Thread.currentThread() + " flag is true. wait @ "
                                + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                        lock.wait();
                    } catch (InterruptedException e) {
                    }
                }
                System.out.println(Thread.currentThread() + " flag is false. running @ "
                        + new SimpleDateFormat("HH:mm:ss").format(new Date()));
            }
        }
    }

    static class Notify implements Runnable {
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println(Thread.currentThread() + " hold lock. notify @ "
                        + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                lock.notifyAll();
                flag = false;
                SleepUtils.second(5);
            }
            synchronized (lock) {
                System.out.println(Thread.currentThread() + " hold lock again. sleep @ "
                        + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                SleepUtils.second(5);
            }
        }
    }
}