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

posted on 2016-08-02 16:24  mh-lhw  阅读(1555)  评论(0编辑  收藏  举报

导航