之前不管读任何书,都告诉你wait方法阻塞,notify是随机唤醒一个,notifyAll方法是一次唤醒所有。我想大部分人在实际面试时候也是这样回答的,但是我今天做了个小小的测试,发现事实并非如此,此疑问来自http://www.jianshu.com/p/f4454164c017文章。
该文中提到,notify实际是唤醒的第一个进入阻塞列表的线程,我也比较疑惑,于是写了个小demo测试。
思路如下,先依次创建100个线程进入wait队列,然后在创建一百个线程去依次唤醒,然后再此时一次唤醒所有。不多说直接贴代码:
先来第一个 100次wait,100次notify,在阻塞时候让线程休眠100秒是为了保证顺序进入阻塞队列,
下面是结果,
看到没有,都是成对出现的,也就是唤醒的线程总是唤醒按顺序入队时候的线程。你们可以自己测试,我测试了很多次一直都是一个结果。这里如果把唤醒的for循环去掉,只唤醒一个,我试了很多次一直都是唤醒的是线程0,也就是第一个进入阻塞队列的。如果是随机唤醒,那么背唤醒的线程就不应该是顺序入队的情况呀。
我们下面测试notifyAll()
代码稍稍更改下
下面是输出结果
结果却是倒叙的。我测试了多次,依然是倒叙,然后同样把阻塞后面的沉睡100毫秒睡眠去掉后多次测试
发现依然是倒叙输出,测试多次,没有改变。难道书上都是错的吗?
我们继续把创建线程时候的睡眠时间去掉,在阻塞前输出当前入队阻塞的线程号,然后依次唤醒所有看输出顺序和入队顺序是否逆一致?
被唤醒的线程顺序是:
我们发现惊奇的一致,notify是按照入队阻塞的逆序一致性进行唤醒操作的。
到这里大家明白了没?
我仅仅是工作不到一年的小白,如果我的测试有错误,还请指正。
网友评论