作者|雷哥来源|Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)做Java开发小伙伴。您应该熟悉wait方法和notify方法。这两个方法在线程通信中的使用频率都很高,但是对于notify方法的唤醒顺序,很多小伙伴都有错误的理解。很多人认为notify是随机唤醒,但是真的是随机唤醒吗?带着这个问题,我们试着让100个线程休眠,然后唤醒100个线程,并且把线程休眠和唤醒的顺序保持两组,最后打印这两组看它们的执行顺序,如果它们的顺序一致,这意味着notify顺序唤醒,否则它随机唤醒。notify测试代码如下:importjava.util.ArrayList;importjava.util.List;publicclassNotifyExample{//保存休眠线程的顺序privatestaticListwaitList=newArrayList<>();//保存唤醒线程的顺序privatestaticListnotifyList=newArrayList<>();publicstaticvoidmain(String[]args)throwsInterruptedException{finalObjectlock=newObject();//休眠100个线程for(inti=0;i<100;i++){StringthreadName=Integer.toString(i);//定义线程名newThread(()->{//获取当前执行线程的线程名StringcurrThreadName=Thread.currentThread().getName();同步(锁定){waitList.add(currThreadName);//存储在等待列表中try{lock.wait();//睡眠线程}catch(InterruptedExceptione){e.printStackTrace();}notifyList.add(currThreadName);//存储唤醒列表}},threadName).start();}Thread.sleep(1000);//唤醒100个线程for(inti=0;i<100;i++){synchronized(lock){lock.notify();//唤醒线程}}//打印2个线程列表System.out.println("waitingthreadorder:"+waitList);System.out.println("唤醒线程顺序:"+waitList);}}上面程序的执行结果如下图所示:从上面的打印结果可以看出,使用notify并不是随机唤醒,而是顺序唤醒,虽然上面的代码可以证明这个结论,但是在为了更清楚的说明这个问题,我们查看了notify的实现源码,其源码内容如下:简单翻译一下上面的关键内容,notify选择唤醒的线程是任意的,但是具体实现要看虚拟机也就是说notify的唤醒规则最终取决于JVM厂商。不同的制造商可能有不同的实现。比如阿里的JVM和Oracle的JVM对于notify的唤醒规则可能不一样。作为一个普通的程序员,我们要研究的是官方的JVM,也就是HotSpot虚拟机。它的notify实现源码在ObjectMonitor.cpp中。具体源码如下:DequeueWaiter方法实现源码如下:从上面的源码我们可以看出,每次唤醒时,都会从_WaitSet等待集合中获取第一个元素进行出队操作时间,也说明notify是顺序唤醒的。综上所述,notify唤醒线程的规则是随机唤醒还是顺序唤醒取决于JVM的具体实现。作为主流的HotSpot虚拟机,notify唤醒规则是顺序的,即notify会根据线程的休眠顺序依次唤醒线程。