看这本书之前,对wait和notify认识大概就是,调用wait的线程A堵塞之后,一旦另外有线程调用notify方法。线程A会立马从wait方法处返回。看完这本书后。发现自己的认识实在太肤浅了。。。。。
。
线程调用wait()后,会释放已经获得的锁。
同一时候进入Waiting状态,而非Blocked状态。唯独等待其它的线程调用notify()方法且释放锁之后。当前线程才会从wait()方法处返回。只发出通知是不够用的。还须要发出通知的线程释放锁。
然而notify()方法的调用并不意味着锁的释放。
贴出原书的demo,稍作了些改动。
/** * */ package chapter04; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.TimeUnit; /** * 6-11 */ public class WaitNotify { private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); static boolean flag = true; static Object lock = new Object(); public static void main(String[] args) { Thread waitThread = new Thread(new Wait(), "WaitThread"); waitThread.start(); sleepSeconds(1); Thread notifyThread = new Thread(new Notify(), "NotifyThread"); notifyThread.start(); } static class Wait implements Runnable { public void run() { synchronized (lock) { // 当条件不满足时,继续wait,同一时候释放了lock的锁 while (flag) { try { System.out.println(CuttentThreadName() + " flag is true. wait @ " + sdf.format(new Date())); lock.wait(); System.out.println(CuttentThreadName() + " gained lock again. wait @ " + sdf.format(new Date())); } catch (InterruptedException e) { e.printStackTrace(); } } // 条件满足时。完毕工作 System.out.println(CuttentThreadName() + " flag is false. running @ " + sdf.format(new Date())); } } } private static String CuttentThreadName() { return Thread.currentThread().getName(); } static class Notify implements Runnable { @Override public void run() { // 加锁,拥有lock的Monitor synchronized (lock) { // 获取lock的锁。然后进行通知,通知时不会释放lock的锁, // 直到当前线程释放了lock后,WaitThread才干从wait方法中返回 System.out.println(CuttentThreadName() + " hold lock. notify @ " + sdf.format(new Date())); lock.notifyAll(); flag = false; sleepSeconds(5); System.out.println(CuttentThreadName() + " is releasing lock @ " + sdf.format(new Date())); } // 再次加锁 synchronized (lock) { System.out.println(CuttentThreadName() + " hold lock again. sleep @ " + sdf.format(new Date())); sleepSeconds(5); System.out.println(CuttentThreadName() + " is releasing lock @ " + sdf.format(new Date())); } } } private static void sleepSeconds(int timeout) { try { TimeUnit.SECONDS.sleep(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } }
输出结果为:
WaitThread flag is true. wait @ 20:58:32 NotifyThread hold lock. notify @ 20:58:33 NotifyThread is releasing lock @ 20:58:38 NotifyThread hold lock again. sleep @ 20:58:38 NotifyThread is releasing lock @ 20:58:43 WaitThread gained lock again. wait @ 20:58:43 WaitThread flag is false. running @ 20:58:43
通过输出结果,我们能够发现几个问题。
1.NotifyThread调用notifyAll()方法后,WaitThread并没有立马从wait()方法处返回。
由于这个时候NotifyThread并没有释放锁。
2.程序61行,NotifyThread第一次释放锁,然而WaitThread不争气,并没有抢到这把锁。依然处于Blocked状态。
3.直到67行。NotifyThread再一次释放锁。WaitThread获得了锁,这才从wait()处返回继续运行。
4.线程从wait()方法返回的前提是,获得synchronized须要的锁。
分析完原书的demo之后,是否有跟我一样的感觉,以前的认识是那么的too young too simple。