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

Object中的wait和notify方法详解

时间:2023-04-01 15:59:32 Java

我们的讲解从一个IllegalMonitorStateException的处理开始。小A写的代码抛出java.lang.IllegalMonitorStateException异常信息。publicclassWaitDemo{publicstaticvoidmain(String[]args)throwsException{Objecto=newObject();o.等待();//业务逻辑代码}}小A通过查看源码确认抛出IllegalMonitorStateException异常是因为当前线程在调用wait方法时没有获取到调用对象的锁。抛出:IllegalMonitorStateException–如果当前线程不是对象监视器的所有者。根据错误原因,将代码改成如下,业务代码运行正常。publicclassWaitDemo{publicstaticvoidmain(String[]args)throwsException{Objecto=newObject();同步(o){o.wait();}//业务逻辑代码}}通过这次异常处理小A意识到自己对wait和notify方法理解不够,导致了异常的发生。让我们一起学习等待和通知方法。介绍了wait和notify方法。wait和notify是在Object类中定义的方法。调用这两个方法的前提条件:当前线程拥有调用者的锁。wait方法有几个重载方法,但它们最终都调用了wait本地方法,如下所示。调用wait方法后,当前线程将进入等待状态,直到其他线程调用该对象的notify和notifyAll方法或指定的等待时间结束。publicfinalnativevoidwait(longtimeout)throwsInterruptedException;notify和notifyAll方法,两者的区别在于notify方法唤醒一个等待调用对象的线程,而notifyAll方法唤醒所有等待调用对象的线程。那么唤醒后的线程可以直接执行吗?答案是否定的。被唤醒的线程需要获得调用对象的锁才能继续执行。publicfinalnativevoidnotify();publicfinalnativevoidnotifyAll();使用场景和代码示例wait和notify方法可以用在多线程的通知场景,比如共享变量count,写线程和读线程交替写读。如下代码所示。packageorg.example;publicclassWaitDemo{privatestaticintcount=0;私有静态对象o=新对象();publicstaticvoidmain(String[]args)throwsInterruptedException{Writew=newWrite();读r=newRead();w.开始();//为了保证写线程序先获取到对象锁Thread.sleep(1000);r.开始();}staticclassWriteextendsThread{@Overridepublicvoidrun(){while(true){synchronized(o){o.notify();计数++;尝试{Thread.sleep(100);o.等待();}catch(InterruptedExceptione){e.printStackTrace();}}}}}staticclassReadextendsThread{@Overridepublicvoidrun(){while(true){synchronized(o){System.out.println(计数);o.通知();尝试{Thread.sleep(100);o.等待();}catch(InterruptedExceptione){e.printStackTrace();}}}}}}运行上面代码的结果如下图所示:1234567891011121314151617181920212223符合我们的预期,count的值是按顺序输出的。总结使用wait和notify方法有以下几点需要注意在调用wait和notify方法时,需要获取调用对象的锁(monitor)。调用wait方法后,当前线程进入等待状态并释放锁。等待线程被notify唤醒后,需要等待调用对象的锁(monitor),才能继续执行业务逻辑。