概述
wait和sleep的区别,这个确实是面试中非常常见的一道题目,这里我们通过源码并结合示例来一起加深下对wait和sleep的理解 。
主要有4点不同
- sleep是Thread的方法,wait是Object的方法
- sleep不会释放锁(Monitor), wait会让当前线程释放锁
- sleep 不依赖 Monitor,但是wait需要依赖Monitor
- sleep方法不需要被唤醒,wait需要唤醒 (wait(long millons) 方法除外)
接下来我们分别来看下这4点区别
区别
sleep是Thread的方法,wait是Object的方法
直接看下源码即可
Object#wait
Thread#sleep
sleep不会释放锁(Monitor), wait会让当前线程释放锁
sleep不会释放锁(Monitor) 举个例子
package com.artisan.test; import java.util.Date; import java.util.stream.Stream; public class SleepAndWaitDiffDemo { private final static Object LOCK = new Object(); private static void method1() { synchronized (LOCK){ System.out.println(Thread.currentThread().getName() + " -- " + new Date()); try { Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { // 开启两个线程 Stream.of("T1","T2").forEach(threadName -> { new Thread(threadName){ @Override public void run() { super.run(); // 调用methood1 method1(); } }.start(); }); } }
输出
wait会让当前线程释放锁
package com.artisan.test; import java.util.Date; import java.util.stream.Stream; public class SleepAndWaitDiffDemo { private final static Object LOCK = new Object(); private static void method2() { synchronized (LOCK){ System.out.println(Thread.currentThread().getName() + " -- " + new Date()); try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { // 开启两个线程 Stream.of("T1","T2").forEach(threadName -> { new Thread(threadName){ @Override public void run() { super.run(); // 调用methood2 method2(); } }.start(); }); } }
sleep 不依赖 Monitor,但是wait需要依赖Monitor
package com.artisan.test; public class SleepAndWaitDiffDemo { private final static Object LOCK = new Object(); private static void method1() { try { Thread.sleep(2_000); System.out.println("method1休眠2秒结束"); } catch (InterruptedException e) { e.printStackTrace(); } } private static void method2() { try { // 不加synchronized关键字,会抛出IllegalMonitorStateExceptio LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { method1(); method2(); } }
运行结果
如何改呢?
private static void method2() { synchronized (LOCK){ try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }
synchronized (LOCK),然后 LOCK.wait即可 。
sleep方法不需要被唤醒,wait需要唤醒 (wait(long millons) 方法除外)
从 sleep不会释放锁(Monitor), wait会让当前线程释放锁 这个例子中,我们可以看到sleep方法执行后,整个主线程就退出了,但 wait方法的,T1 和 T2 都处于waiting状态了,需要被唤醒才能继续执行…