java wait和notify
wait方法是Object类的方法,这意味着所有的Java类都可以调用该方法。wait方法貌似能让当前线程暂停执行完,其它也没有什么用处,但是你真的理解了wait方法了吗?wait方法在java中很多地方都有用到,实现Thread类的join方法,内部就使用了wait,所以wait方法需要大家去掌握。
wait是在当前线程持有wait对象锁的情况下,暂时放弃锁,并让出CPU资源,并积极等待其它线程调用同一对象的notify或者notifyAll方法。注意,即使只有一个线程在等待,并且有其它线程调用了notify或者notifyAll方法,等待的线程只是被激活,但是它必须得再次获得锁才能继续往下执行。换言之,即使notify被调用,但只要锁没有被释放,原等待线程因为未获得锁仍然无法继续执行。测试代码如下所示
/** * Created by lhw on 16-7-29. */ public class Demo { public static void main(String[] args) { Thread thread1 = new Thread(() -> { synchronized (Demo.class) { try { System.out.println(new Date() + " Thread1 is running"); Demo.class.wait(); System.out.println(new Date() + " Thread1 ended"); } catch (Exception ex) { ex.printStackTrace(); } } }); thread1.start(); Thread thread2 = new Thread(() -> { synchronized (Demo.class) { try { System.out.println(new Date() + " Thread2 is running"); Demo.class.notify(); System.out.println(new Date() + " Thread2 notify"); // Don't use sleep method to avoid confusing for(long i = 0; i < 200000; i++) { for(long j = 0; j < 100000; j++) {} } System.out.println(new Date() + " Thread2 release lock"); } catch (Exception ex) { ex.printStackTrace(); } } for(long i = 0; i < 200000; i++) { for(long j = 0; j < 100000; j++) {} } System.out.println(new Date() + " Thread2 ended"); }); // Don't use sleep method to avoid confusing for(long i = 0; i < 200000; i++) { for(long j = 0; j < 100000; j++) {} } thread2.start(); } } 输出: Tue Aug 02 16:10:29 CST 2016 Thread1 is running Tue Aug 02 16:10:35 CST 2016 Thread2 is running Tue Aug 02 16:10:35 CST 2016 Thread2 notify Tue Aug 02 16:10:41 CST 2016 Thread2 release lock Tue Aug 02 16:10:41 CST 2016 Thread1 ended Tue Aug 02 16:10:47 CST 2016 Thread2 ended
从运行结果可以看出:
thread1执行wait后,暂停执行
thread2执行notify后,thread1并没有继续执行,因为此时thread2尚未释放锁,thread1因为得不到锁而不能继续执行
thread2执行完synchronized语句块后释放锁,thread1得到通知并获得锁,进而继续执行
注意:wait方法需要释放锁,前提条件是它已经持有锁。所以wait和notify(或者notifyAll)方法都必须被包裹在synchronized语句块中,并且synchronized后锁的对象应该与调用wait方法的对象一样。否则抛出IllegalMonitorStateException