等待/通知的经典范式

该范式分为两部分,分别针对等待方(消费者)和通知方(生产者)。

等待方遵循如下原则。

(1)获取对象的锁。

(2)如果条件不满足,那么调用对象的wait()的方法,被通知后仍要检查条件。

(3)条件满足则执行对应的逻辑。

对应的伪代码如下。

synchronized(对象){
    while(条件不满足){
          对象.wait();
    }          
     对应的处理逻辑
}

通知方遵循如下原则。

(1)获取对象的锁。

(2)改变条件。

(3)通知所有等待在对象上的线程。

对应的伪代码如下。

synchronized(对象){
    改变条件;
    对象.notifyAll();         
}

 例:创建两个线程------WaitThread和NotifyThread,前者检查flag值是否为false,如果是false,进行后续操作,否则在lock上等待,后者在睡眠了一段时间后对lock进行通知并修改条件。

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 InterruptedException {
        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() {
            // 加锁,拥有lock的Monitor
            synchronized (lock) {
                //当条件不满足时,继续wait,同时释放了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) {
                        e.printStackTrace();
                    }
                }
                // 条件满足时,完成工作
                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() {
            //加锁,拥有lock的Monitor
            synchronized (lock) {
                // 获取lock的锁,然后进行通知,通知时不会释放lock的锁
                // 直到当前线程释放了lock后,WaitThread才能从wait方法中返回
                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);
                }
            }
        }
    }
}

 

 

posted @ 2019-11-07 20:14  wangAQS  阅读(256)  评论(0)    收藏  举报