目的
方便自己后续面试复习方便
资源
sleep VS wait
共同点
wait(), wait(long)和sleep(long)的效果都是让当前线程放弃CPU的使用权, 进入阻塞状态
不同点
方法归属不同
① speep(long)是Thread的静态方法
② wait(), wait(long) 都是Object的成员方法, 每个对象都有
醒来时机不同
① 执行sleep(long)和wait(long)的线程都会在等待相应的毫秒后醒来
② wait(long)和wait(long)还可以被notify唤醒, wait()如果不唤醒就一直等下去
③ 它们都可以被打断唤醒
锁特性不同
① wait方法的调用必须先获取wait对象的锁, 而sleep则无此限制
② wait方法执行后会释放对象锁, 允许其他线程获得该对象锁 (我放弃, 但你们还可以用)
③ sleep如果在synchronized代码块中执行, 并不会释放对象锁 (我放弃, 你们也用不了)
自测试程序
/**
* 面试题: wait和sleep
*
* @author xiaozhengN [email protected]
* @since 2022-10-23 10:25:28
**/
@Slf4j
public class WaitVsSleep {
static final Object LOCK = new Object();
public static void main(String[] args) throws InterruptedException {
// wait 必须配合锁一起使用
illegalWait();
waitting();
sleeping(false);
sleeping(true);
}
private static void sleeping(Boolean isInterrupted) throws InterruptedException {
log.info("test sleeping() start, param is {}", isInterrupted);
Thread t1 = new Thread(() -> {
synchronized (LOCK) {
try {
log.info("current thread: {} sleeping...", Thread.currentThread().getName());
// Thread.sleep() 会继续持有 LOCK 对象的锁资源, 直到自己的事情做完(5s)
Thread.sleep(5000L);
log.info("current thread: {} sleeping end...", Thread.currentThread().getName());
} catch (InterruptedException e) {
log.info("current thread: {} has interrupted...", Thread.currentThread().getName(), e);
}
}
}, "T1");
t1.start();
Thread.sleep(100);
if (isInterrupted) {
t1.interrupt();
}
synchronized (LOCK) {
log.info("current thread: {} other...", Thread.currentThread().getName());
}
log.info("test sleeping() end...");
}
private static void waitting() throws InterruptedException {
log.info("test waitting() start...");
new Thread(() -> {
synchronized (LOCK) {
try {
log.info("current thread: {} waiting...", Thread.currentThread().getName());
// wait() 不会去持续 5s 去占有 LOCK 的锁资源
LOCK.wait(5000L);
} catch (InterruptedException e) {
log.info("current thread: {} interrupted...", Thread.currentThread().getName(), e);
}
}
}, "T1").start();
Thread.sleep(100);
synchronized (LOCK) {
log.info("current thread: {} other...", Thread.currentThread().getName());
}
log.info("test waitting() end...");
}
private static void illegalWait() throws InterruptedException {
try {
LOCK.wait();
} catch (Exception e) {
log.error("执行 sleep 异常: ", e);
}
}
}
日志分析
// wait() 必须要持有对象的资源, 才可以让对象wait(), 否则: IllegalMonitorStateException
2022-10-23 11:07:27,634 ERROR [main.daily.WaitVsSleep] - 执行 sleep 异常:
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at main.daily.WaitVsSleep.illegalWait(WaitVsSleep.java:71)
at main.daily.WaitVsSleep.main(WaitVsSleep.java:18)
// 注意这个时间: wait() 并没有持续独占 LOCK 锁资源 5 秒
2022-10-23 11:07:27,636 INFO [main.daily.WaitVsSleep] - test waitting() start...
2022-10-23 11:07:27,665 INFO [main.daily.WaitVsSleep] - current thread: T1 waiting...
2022-10-23 11:07:27,764 INFO [main.daily.WaitVsSleep] - current thread: main other...
2022-10-23 11:07:27,764 INFO [main.daily.WaitVsSleep] - test waitting() end...
// 不去打断 sleep(), 支持独占锁资源 5s 才释放
2022-10-23 11:12:14,677 INFO [main.daily.WaitVsSleep] - test sleeping() start, param is false
2022-10-23 11:12:14,678 INFO [main.daily.WaitVsSleep] - current thread: T1 sleeping...
2022-10-23 11:12:19,678 INFO [main.daily.WaitVsSleep] - current thread: T1 sleeping end...
2022-10-23 11:12:19,678 INFO [main.daily.WaitVsSleep] - current thread: main other...
// 打断, 直接释放锁资源
2022-10-23 11:12:19,678 INFO [main.daily.WaitVsSleep] - test sleeping() end...
2022-10-23 11:12:19,678 INFO [main.daily.WaitVsSleep] - test sleeping() start, param is true
2022-10-23 11:12:19,678 INFO [main.daily.WaitVsSleep] - current thread: T1 sleeping...
2022-10-23 11:12:19,779 INFO [main.daily.WaitVsSleep] - current thread: T1 has interrupted...
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at main.daily.WaitVsSleep.lambda$sleeping$0(WaitVsSleep.java:31)
at java.lang.Thread.run(Thread.java:745)
2022-10-23 11:12:19,779 INFO [main.daily.WaitVsSleep] - current thread: main other...
2022-10-23 11:12:19,779 INFO [main.daily.WaitVsSleep] - test sleeping() end...