面试必问的试题解析
sleep 和 wait 有什么联系与区别
程序猿出品 面试辅导入职阶梯顺利入职大厂,赢得百万年薪,是每个入职It业的程序员所渴望的,但是僧多粥少,能够实现愿望的毕竟是少数。如何在激烈的竞争中脱颖而出,迎娶白富美...呃,不是,赢取Offer,走上人生巅峰,成了每个职场萌新关心的重点。
Java面试宝典系列,不敢说助推您事业成功,只要能帮助您事业大厦添得只砖片瓦,就足以宽慰老怀。
▶▶▶▶▶ sleep 和 wait 有什么联系和区别sleep 和 wait 几乎是所有面试中必问的题,但想完全回答正确似乎没那么简单。
对于 sleep 和 wait 的区别,通常的回答是这样的:
wait 必须搭配 synchronize 一起使用,而 sleep 不需要;
进入 wait 状态的线程能够被 notify 和 notifyAll 线程唤醒,而 sleep 状态的线程不能被 notify 方法唤醒;
wait 通常有条件地执行,线程会一直处于 wait 状态,直到某个条件变为真,但是 sleep 仅仅让你的线程进入睡眠状态;
wait 方法会释放对象锁,但 sleep 方法不会;
在调用 wait 方法之后,线程会变为WATING 状态,而调用 sleep 方法之后,线程会变为 TIMED_WAITING 状态。
我们现在来具体验证一下代码。
先来看一个wait的例子
public class WaitDemo { private static Object locker = new Object(); public static void main(String[] args) throws InterruptedException { WaitDemo waitDemo = new WaitDemo(); // 启动新线程,防止主线程被休眠 new Thread(() -> { try { waitDemo.doWait(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); Thread.sleep(200); // 此行本身没有意义,是为了确保 wait() 先执行再执行 notify() waitDemo.doNotify(); } /** * 执行 wait() */ private void doWait() throws InterruptedException { synchronized (locker) { System.out.println("wait start."); locker.wait(); System.out.println("wait end."); } } /** * 执行 notify() */ private void doNotify() { synchronized (locker) { System.out.println("notify start."); locker.notify(); System.out.println("notify end."); } } } |
以上程序的执行结果为:
wait start. notify start. notify end. wait end. |
解析:我们在 doWait 方法上加了一把锁,在调用完wait() 方法后,doNofity 方法就能正常执行,说明此时对象锁已经释放,最后才执行到 wait end 输出块。
同样我们来看看 sleep 是如何执行这段逻辑的。
public class WaitDemo { private static Object locker = new Object(); public static void main(String[] args) throws InterruptedException { WaitDemo waitDemo = new WaitDemo(); // 启动新线程,防止主线程被休眠 new Thread(() -> { synchronized (locker) { try { System.out.println("sleep start."); Thread.sleep(1000); System.out.println("sleep end."); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); Thread.sleep(200); waitDemo.doNotify(); } /** * 执行 notify() */ private void doNotify() { synchronized (locker) { System.out.println("notify start."); locker.notify(); System.out.println("notify end."); } } |
sleep 模式下执行的结果是这样的:
sleep start. sleep end. notify start. notify end. |
这说明了在 sleep 模式下,对象锁没有释放,notify 块直到 sleep 结束,才得到执行。
主讲人:程序猿
Java面试宝典