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

面试实战25:sleep和wait有什么区别

时间:2023-04-01 17:36:55 Java

sleep方法和wait方法都是用来让线程进入休眠状态的,而且sleep和wait方法都可以响应interrupt中断,即在线程休眠过程中,如果收到中断信号后,可以响应并抛出InterruptedException异常。睡眠和等待有什么区别?接下来,我们一起来看看吧。区别1:语法使用了不同的wait方法,必须和synchronized一起使用,否则会在运行时抛出IllegalMonitorStateException,如下代码所示:乍一看代码好像没问题,编译器并没有报错一个错误。但是,当我们运行上面的程序时,会出现如下错误:虽然sleep可以单独使用,但是不需要和synchronized一起使用。区别二:不同的班级。wait方法属于Object类的方法,sleep属于Thread类的方法,如下图:区别3:唤醒方式不同超时,线程会自动唤醒。wait方法不能传递任何参数。当不传递任何参数时,意味着它将永远休眠。在另一个线程调用notify或notifyAll之前,睡眠线程无法被唤醒。也就是说sleep方法具有主动唤醒功能,而没有传递任何参数的wait方法只能被动唤醒。区别四:释放的锁资源不同。wait方法会主动释放锁,sleep方法不会。接下来,我们用代码来演示一下两者的区别。睡眠不会释放锁。接下来使用sleep让线程休眠2s,然后尝试在另一个线程中获取公锁。如果能够获取到锁,则说明sleep在sleep的过程中会释放锁,否则意味着不会释放锁。实现代码如下:publicstaticvoidmain(String[]args)throwsInterruptedException{Objectlock=newObject();newThread(()->{synchronized(lock){System.out.println("新线程已获取锁:"+LocalDateTime.now());try{//休眠2sThread.sleep(2000);System.out.println("新线程已释放锁:"+LocalDateTime.now());}catch(InterruptedExceptione){e.printStackTrace();}}}).start();//等待新线程先获取锁Thread.sleep(200);System.out.println("主线程尝试获取锁:"+LocalDateTime.now());//新线程休眠后,尝试获取锁synchronized(lock){System.out.println("主线程已获取锁:"+LocalDateTime.now());}}上面代码的执行结果如下图所示:从上面的结果可以看出,在调用sleep之后,主线程尝试获取锁但是失败了。只有执行完sleep后释放锁,主线程才能正常拿到锁。这说明sleep并没有释放锁。等待释放锁再用同样的方法,将sleep换成wait,线程休眠后,尝试在另一个线程获取锁,实现代码如下:publicstaticvoidmain(String[]args)throwsInterruptedException{对象锁=newObject();newThread(()->{synchronized(lock){System.out.println("新线程已获取锁:"+LocalDateTime.now());try{//休眠2slock.wait(2000);System.out.println("新线程解锁:"+LocalDateTime.now());}catch(InterruptedExceptione){e.printStackTrace();}}}).start();//等等新线程首先获取锁Thread.sleep(200);System.out.println("主线程尝试获取锁:"+LocalDateTime.now());//新线程休眠后,尝试获取锁synchronized(lock){System.out.println("主线程已获取锁:"+LocalDateTime.now());}}上面代码的执行结果如下图所示:从上面的结果可以看出,当调用wait时,主线程立即尝试获取锁成功,也就是说锁是等待睡眠时释放。区别五:线程进入不同的状态。调用sleep方法线程会进入TIMED_WAITING限时等待状态,而调用不带参数的wait方法线程会进入WAITING无限等待状态。代码演示:publicstaticvoidmain(String[]args)throwsInterruptedException{Objectlock=newObject();Threadt1=newThread(()->{synchronized(lock){try{//休眠2slock.wait();}catch(InterruptedExceptione){e.printStackTrace();}}});t1.开始();Threadt2=newThread(()->{try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}});t2.开始();线程.睡眠(200);System.out.println("进入状态后等待():"+t1.getState());System.out.println("sleep(2000)然后进入状态:"+t2.getState());}上面代码的执行结果如下:总结sleep和wait可以让线程休眠,它们可以响应中断interrupt,但两者的区别主要体现在:语法不同,类不同,唤醒方式不同,释放锁不同,线程进入状态不同。判断是非在己,名誉在人,得失在数。公众号:Java面试真题分析面试合集:https://gitee.com/mydb/interview