等待/通知的经典范式
该范式分为两部分,分别针对等待方(消费者)和通知方(生产者)。
等待方遵循如下原则。
(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); } } } } }

浙公网安备 33010602011771号