博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
wait(),notify() 和 notifyAll()使用及原理
阅读量:4149 次
发布时间:2019-05-25

本文共 2137 字,大约阅读时间需要 7 分钟。

    简述:在上一篇日志中,分析了synchronized关键字,其底层是对对象加锁,通过锁来限制同一时刻只有一个线程来访问同步块,而wait方法是让当前线程失去对锁的拥有权,让出锁,让其他线程进入,又有monitor监视器是属于对象的,那么wait方法及notify也是数据对象的,他们都是对某一个对象的锁的获取和释放。基于以上,可以看出来对于wait方法是建立在锁之上的,notify/notifyAll 方法也是建立在锁的基础上,他们会唤醒在当前锁对象上面等待的线程,直到当前线程执行完synchronized方法体以后,会唤醒在当前锁上等待的线程。所以对notify/notifyAll 方法的调用最好是在synchronized方法的最后一步,执行完notify/notifyAll 之后就会释放掉锁。

先来看一个列子

public class NotifyTest {    public synchronized void testWait() {        System.out.println(Thread.currentThread().getName() + " Start----");        try{            wait();        }catch (Exception e){            e.printStackTrace();        }        System.out.println(Thread.currentThread().getName() + " End------");    }    public static void main(String[] args) throws Exception{        final NotifyTest test = new NotifyTest();        for(int i = 0; i < 5; i++){            new Thread(new Runnable() {                @Override                public void run() {                    test.testWait();                }            }).start();        }        Thread.sleep(1000);        synchronized (test){            test.notify();        }       Thread.sleep(3000);        System.out.println("---------------我是分割线-------------");        synchronized (test){            test.notifyAll();        }    }}

下面这个程序的输出结果是:

Thread-0 Start----Thread-1 Start----Thread-3 Start----Thread-4 Start----Thread-2 Start----Thread-0 End---------------------我是分割线-------------Thread-2 End------Thread-4 End------Thread-3 End------Thread-1 End------

在notify方法调用时,只会去唤醒等待池中的一个线程,notifyAll是会唤醒所有的等待线程。

如果没有被唤醒的线程,将一直处于等待池中,由于我们的线程没有设置成daemon线程,所以处于等待池中的线程如果一直没有被唤醒,那么我们的程序将不会停止。

总结:

1、如果一个线程调用了wait方法,那么该线程首先需要获取到这个对象的锁(换句话说,一个线程如果调用了某个方法的wait方法,那么该wait方法必须是在synchronized方法中的)

2、如果一个线程调用了wait方法,那么当前线程就会释放掉线程的锁。(这个是wait和sleep方法不同的地方)

3、在java中一个对象,会有两个池(锁池,等待池),如果一个线程调用了wait方法,那么该线程进入该对象的等待池中(释放锁),如果未来的某一刻,另外一个线程调用了这个对象的notify方法,或者notifyAll,那么在等待池中的线程就会起来进入该对象的锁池中,参与到获取锁的竞争当中,如果获取锁成功,将沿着wait方法之后的代码执行(这就是为什么生产者消费者中,使用while来判断状态,而不是if)

notify和notifyAll方法并不会去释放当前锁对象,而是通过moniterexist来释放,也就是说,当前所述的代码块在执行结束之后,回去释放掉锁,只有在锁被释放掉之后,等待池中的线程进入到锁池,去竞争锁资源。

以上是关于wait,notify及notifyAll方法的介绍。如有错误,欢迎指正~

参考:

转载地址:http://xovti.baihongyu.com/

你可能感兴趣的文章
kotlin面试题!一口气拿了9家公司的offer,已拿offer入职
查看>>
深入解析android核心组件和应用框架,Android面试题及解析
查看>>
温故而知新!微信小程序的事件处理,吊打面试官系列!
查看>>
灵魂拷问!Android性能优化之APK优化,系列篇
查看>>
焦虑的移动互联网开发者如何破局?BAT大厂面试总结
查看>>
爆赞!Android岗大厂面试官常问的那些问题,论程序员成长的正确姿势
查看>>
爆赞!Android岗大厂面试官常问的那些问题,论程序员成长的正确姿势
查看>>
爱了爱了!Android平台HTTPS抓包解决方案及问题分析,面试必问
查看>>
爱了爱了!Android开发者值得深入思考的几个问题,送大厂面经一份!
查看>>
牛笔了!Android黑科技保活实现原理揭秘,深度好文
查看>>
牛笔了!这些面试官常问的开发面试题你都掌握好了吗?看这一篇就够了!
查看>>
看完不会的来打我!Android免打包多渠道统计如何实现?面试必会
查看>>
看完全都会了!Android开发热门前沿知识,积累总结
查看>>
看完吊打面试官!海量算法高频面试题精编解析,附带学习经验
查看>>
看完豁然开朗!一线互联网大厂面试真题系统收录!社招面试心得
查看>>
真是经典中的经典!Android开发你需要了解的那些事,深度好文
查看>>
程序员的中年危机,我想谈谈关于Android面试那些事,深度好文
查看>>
程序员真的是吃青春饭吗?面试官6个灵魂拷问,分享一点面试小经验
查看>>
程序员进阶!Android黑科技保活实现原理揭秘,分享一点面试小经验
查看>>
算法太TM重要了!2021年Android春招面试经历,这原因我服了
查看>>