当前位置: 首页 > 后端技术 > Java

访谈突击41:notify是随机唤醒吗?

时间:2023-04-01 16:00:19 Java

作为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();synchronized(lock){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("Waitingthreadsequence:"+waitList);System.out.println("唤醒线程顺序:"+waitList);}}上述程序执行结果如下图所示:从上面的打印结果可以看出,使用notify并不是随机唤醒,而是顺序唤醒。虽然上面的代码可以证明这个结论,但是为了更清楚的说明这个问题,我们查看notify的实现源码如下:简单翻译一下上面的关键内容,notify选择唤醒的线程是任意的,但是具体实现取决于JVM,也就是说notify的唤醒规则,最终取决于JVM厂商,不同的厂商可能有不同的实现,比如阿里的JVM和Oracle的JVM,notify的唤醒规则可能不同。作为一个普通的程序员,我们要研究的是官方的JVM,也就是HotSpot虚拟机。它的notify实现源码在ObjectMonitor.cpp中。具体源码如下:DequeueWaiter方法实现源码如下:从上面的源码我们可以看出,每次唤醒时,都会从_WaitSet等待集合中获取第一个元素进行出队操作时间,也说明notify是顺序唤醒的。综上所述,notify唤醒线程的规则是随机唤醒还是顺序唤醒取决于JVM的具体实现。作为主流的HotSpot虚拟机,notify唤醒规则是顺序的,即notify会根据线程的休眠顺序依次唤醒线程。判断是非在自己,名誉在别人,得失在人数。公众号:Java面试真题分析面试合集:https://gitee.com/mydb/interview