面试突击25:sleep和wait有什么区别
sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应,并抛出 InterruptedException 异常。那 sleep 和 wait 的区别都有哪些呢?接下来,我们一起来看。
区别一:语法使用不同
wait 方法必须配合 synchronized 一起使用,不然在运行时就会抛出 IllegalMonitorStateException 的异常,如下代码所示:

初看代码好像没啥问题,编译器也没报错,然而当我们运行以上程序时就会发生如下错误:

而 sleep 可以单独使用,无需配合 synchronized 一起使用。
区别二:所属类不同
wait 方法属于 Object 类的方法,而 sleep 属于 Thread 类的方法,如下图所示:

区别三:唤醒方式不同
sleep 方法必须要传递一个超时时间的参数,且过了超时时间之后,线程会自动唤醒。而 wait 方法可以不传递任何参数,不传递任何参数时表示永久休眠,直到另一个线程调用了 notify 或 notifyAll 之后,休眠的线程才能被唤醒。也就是说 sleep 方法具有主动唤醒功能,而不传递任何参数的 wait 方法只能被动的被唤醒。
区别四:释放锁资源不同
wait 方法会主动的释放锁,而 sleep 方法则不会。接下来我们使用代码的方式来演示一下二者的区别。
sleep 不释放锁
接下来使用 sleep 是线程休眠 2s,然后在另一个线程中尝试获取公共锁,如果能够获取到锁,则说明 sleep 在休眠时会释放锁,反之则说明不会释放锁,实现代码如下:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
System.out.println("新线程获取到锁:" + LocalDateTime.now());
try {
// 休眠 2s
Thread.sleep(2000);
System.out.println("新线程获释放锁:" + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// 等新线程先获得锁
Thread.sleep(200);
System.out.println("主线程尝试获取锁:" + LocalDateTime.now());
// 在新线程休眠之后,尝试获取锁
synchronized (lock) {
System.out.println("主线程获取到锁:" + LocalDateTime.now());
}
}
以上代码的执行结果如下图所示:

从上述结果可以看出,在调用了 sleep 之后,在主线程里尝试获取锁却没有成功,只有 sleep 执行完之后释放了锁,主线程才正常的得到了锁,这说明 sleep 在休眠时并不会释放锁。
wait 释放锁
接下来使用同样的方式,将 sleep 替换成 wait,在线程休眠之后,在另一个线程中尝试获取锁,实现代码如下:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
System.out.println("新线程获取到锁:" + LocalDateTime.now());
try {
// 休眠 2s
lock.wait(2000);
System.out.println("新线程获释放锁:" + LocalDateTime.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// 等新线程先获得锁
Thread.sleep(200);
System.out.println("主线程尝试获取锁:" + LocalDateTime.now());
// 在新线程休眠之后,尝试获取锁
synchronized (lock) {
System.out.println("主线程获取到锁:" + LocalDateTime.now());
}
}
以上代码的执行结果如下图所示:

从上述结果可以看出,当调用了 wait 之后,主线程立马尝试获取锁成功了,这就说明 wait 休眠时是释放锁的。
区别五:线程进入状态不同
调用 sleep 方法线程会进入 TIMED_WAITING 有时限等待状态,而调用无参数的 wait 方法,线程会进入 WAITING 无时限等待状态。
代码演示:
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock) {
try {
// 休眠 2s
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
Thread.sleep(200);
System.out.println("wait() 之后进入状态:" + t1.getState());
System.out.println("sleep(2000) 之后进入状态:" + t2.getState());
}
以上代码的执行结果如下:

总结
sleep 和 wait 都可以让线程进入休眠状态,并且它们都可以响应 interrupt 中断,但二者的区别主要体现在:语法使用不同、所属类不同、唤醒方式不同、释放锁不同和线程进入的状态不同。
是非审之于己,毁誉听之于人,得失安之于数。
公众号:Java面试真题解析
面试突击25:sleep和wait有什么区别的更多相关文章
- 《【面试突击】— Redis篇》--Redis都有哪些数据类型?分别在哪些场景下使用比较合适?
能坚持别人不能坚持的,才能拥有别人不能拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>--Redis都有哪些数据类型?分别在哪些场景下使用 ...
- 《【面试突击】— Redis篇》-- Redis的线程模型了解吗?为啥单线程效率还这么高?
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的线程模型了解吗?为啥单线程效率还这 ...
- 《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注左上角编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的主从复制?哨兵机制? 在这个 ...
- 《【面试突击】— Redis篇》-- Redis哨兵原理及持久化机制
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis哨兵原理及持久化机制 在这个系列里, ...
- 《【面试突击】— Redis篇》--Redis Cluster及缓存使用和架构设计的常见问题
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>--Redis Cluster及缓存使用和架构设计的 ...
- Oracle DBA面试突击题
一份ORACLE DBA面试题 一:SQL tuning 类 1:列举几种表连接方式 答: Oracle的多表连接算法有Nest Loop.Sort Merge和Hash Join三大类,每一类又可以 ...
- Spring面试问答25题
1.什么是Spring框架?Spring框架有哪些主要模块? Spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题, ...
- 【面试突击】- 2019年125条常见的java面试笔试题汇总(一)
1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部 问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二 ...
- 【面试突击】-Redis常见面试题(二)
1.什么是Redis?简述它的优缺点? Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到 ...
随机推荐
- Solon Web 开发,八、校验、及定制与扩展
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- idea 插件推荐
工欲善其事必先利其器,本文介绍几个自己在开发过程中常用的idea插件 安装方法 idea 里面在线安装 settings>plugins>marketplace 里面搜索安装 idea 官 ...
- Mybatis 学习记录 续
项目结构如下: 1.数据库建表 表名:user 结构: 内容: 2.pom.xml文件更新如下: 注:其中build部分尤其需要重视 <?xml version="1.0" ...
- 2月4日 体温APP开发记录
1.阅读构建之法 现代软件工程(第三版) 2.观看Android开发视频教程最新版 Android Studio开发 3.数据库链接,,数据传输功能测试
- atan2(y,x)和pow(x,y)
atan2(y,x): 函数atan2(y, x)是4象限反正切,求的是y/x的反正切,其返回值为[-π,+π]之间的一个数.它的取值不仅取决于正切值y/x,还取决于点 (x, y) 落入哪个象限: ...
- 第03讲:Flink 的编程模型与其他框架比较
Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 本课时我们主要介绍 ...
- 『无为则无心』Python函数 — 39、Python中异常的传播
目录 1.异常的传播 2.如何处理异常 1.异常的传播 当在函数中出现异常时,如果在函数中对异常进行了处理,则异常不会再继续传播.如果函数中没有对异常进行处理,则异常会继续向函数调用者传播.如果函数调 ...
- find -or 用法
find /opt/IBM/WebSphere85/ -name *loggeter* - or -name *loggetter* | xargs rm -rf
- Photoshop如何快速扣取图标
由于图标往往与背景色区别很大,因此首先使用魔棒工具快速选择出图标 有时候选择出来是图标,有时候是背景色 可以通过选择反向来调节(右键即可) ctrl + J 提取出选择的区域 这时进行等分裁剪即可 点 ...
- Linux 配置 mycat 和 分库分表配置。
Linux 如何配置mycat? 3.配置mycat 3.1.规定linux的用户名和全名不能叫mycat!!!否则mycat会不生效(原因是影响整个linux系统的环境变量导致mycat的配置环境变 ...