sleep、wait方法之间区别
sleep、wait方法之间区别
1.所属的类不同
sleep是Thread类的静态方法,而wait是Object类的成员方法
2.锁机制不一样
- sleep方法:会让出资源调度器为当前线程分配的时间片,也就是放弃cpu的使用权,但是sleep不会释放当前线程持有的锁资源。其缺点就是当其它线程想获得同样的锁资源会被阻塞。
- wait方法:既放弃cpu使用权,也会释放锁资源。即不会阻塞其它线程
请看如下代码:创建两个线程t1、t2,t1获得锁后睡眠5s
@Slf4j
public class TestSleepAndWait {
static final String lock = "abc";
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
synchronized (lock){
log.error("t1线程执行");
try {
//
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"t1");
Thread t2 = new Thread(()->{
// t2获得锁后执行
synchronized (lock){
log.error("t2线程执行");
}
},"t1");
t1.start();
t2.start();
}
}
执行结果:
16:51:01 [t1] gzhu.study.test.TestSleepAndWait - t1线程执行
16:51:06 [t1] gzhu.study.test.TestSleepAndWait - t2线程执行
由日志时间可以看到t2线程执行时间刚好在5s之后,说明t1睡眠过程中,t2一直在阻塞等待t1释放锁。
接下来我们尝试把sleep方法换成wait方法,上述其它代码不变
// t1线程等待
lock.wait();
查看运行结果:
16:57:55 [t1] gzhu.study.test.TestSleepAndWait - t1线程执行
16:57:55 [t1] gzhu.study.test.TestSleepAndWait - t2线程执行
可以看到t1、t2线程几乎在同一时间运行,说明wait方法使线程释放了说资源。值得注意的是,wait方法需要配合锁对象使用,即使用锁对象使当前线程阻塞。
3.调用之后的线程的状态不同
sleep方法调用后,线程进入TIME_WAITING状态,而wait方法调用后,线程会进入WAITING状态。
额外了解一下:什么是等待池?什么是锁池?
等待池就是:线程调用wait方法后,线程会进入一个LIFO(为什么是LIFO下面解释)等待被唤醒,在等待池的线程被唤醒之前是不会去竞争锁资源的。
锁池:存放竞争锁资源的线程,等待池的线程被notify()和notifyAll()方法唤醒之后,会先进入锁池而不是直接获得锁资源执行。另外有一个误区,笔者看到许多博客说sleep方法需要指定时间,而wait方法不需要指定时间其实是错的,如下:
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException
第一种情况:
@Slf4j
public class TestSleepAndWait {
static final String lock = "abc";
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
synchronized (lock){
log.error("t1线程执行");
try {
// t1线程等待
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.error("t1线程继续执行");
}
},"t1");
Thread t2 = new Thread(()->{
// t2获得锁后执行
synchronized (lock){
log.error("t2线程执行");
}
},"t1");
Thread t3 = new Thread(()->{
// t2获得锁后执行
synchronized (lock){
log.error("t3线程执行");
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}
结果:
17:33:03 [t1] gzhu.study.test.TestSleepAndWait - t1线程执行
17:33:03 [t3] gzhu.study.test.TestSleepAndWait - t3线程执行
17:33:03 [t1] gzhu.study.test.TestSleepAndWait - t2线程执行
由于没有唤醒t1线程,即使t2、t3线程释放锁资源后,t1线程也没有继续执行。
第二种情况:
Thread t1 = new Thread(()->{
synchronized (lock){
log.error("t1线程执行");
try {
// t1线程等待
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.error("t1线程继续执行");
}
},"t1");
Thread t2 = new Thread(()->{
// t2获得锁后执行
synchronized (lock){
log.error("t2线程执行");
lock.notify();
while (true){
}
}
},"t1");
t1.start();
t2.start();
运行结果:
17:38:23 [t1] gzhu.study.test.TestSleepAndWait - t1线程执行
17:38:23 [t1] gzhu.study.test.TestSleepAndWait - t2线程执行
即使t1被t2唤醒进入锁池,但是由于t2一直循环未释放锁资源,使得t1也不能立即继续执行。
notify()方法与notifyAll()方法
notifAll方法,是将等待池中所有线程唤醒,并按照LIFO原则唤醒
notify方法是从等待队列中随机唤醒,如果只有一个线程则唤醒一个线程。
sleep、wait方法之间区别的更多相关文章
- jQuery的prop和attr方法之间区别
JQuery.attr(): Get the value of an attribute for the first element in the set of matched elements. J ...
- jquery中使元素显示和隐藏方法之间的区别
在实际的项目开发中,要使一个元素隐藏的方法有很多,比如css的多种属性和jquery的多种方法,虽然他们的作用都是使元素不可见,但是各个方法实现的原理是不一样的.下面主要介绍jquery各个元素隐藏方 ...
- 二.OC基础--1,对象的存储细节,2,#pragma mark指令,3,函数和对象方法的区别,4,对象和方法之间的关系 ,5.课堂习题
1,对象的存储细节, 1. 当创建一个对象的时候:Person *p1 = [Person new],做了三件事情: 1,申请堆内存空间: 2,给实例变量初始化: 3,返回所申请空间的首地址; 2. ...
- 并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别
问题描写叙述: 在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.有一个联合-查找算法(union-find algorithm ...
- ThinkPHP的D方法和M方法的区别
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
- jQuery中的.bind()、.live()和.delegate()之间区别分析
jQuery中的.bind()..live()和.delegate()之间区别分析,学习jquery的朋友可以参考下. DOM树 首先,可视化一个HMTL文档的DOM树是很有帮助的.一个简单的 ...
- Hibernate框架之get和load方法的区别
我们在学习Hibernate框架时,经常会进行修改,删除操作,对于这些操作,我们都应该先加载对象,然后在执行或删除的操作,那么这里Hibernate提供了两种方法按照主键加载对象,也就是我要说的get ...
- Java线程中yield与join方法的区别
长期以来,多线程问题颇为受到面试官的青睐.虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用.之前,我讨论了一个w ...
- M方法和D方法的区别
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
随机推荐
- 2021.02.21cf补题
B. National Project 题意:总长度为n的公路进行维修,天气是有规律性的,连续g天的好天气,连续b天的坏天气,必须在好天气进行维护,问至少维护n的一半,那么至少需要多少天 思路:必须是 ...
- Spring cloud 基础框架集成
Spring cloud 基础框架集成 1. 注册中心 -eurekar 1. pom依赖 <?xml version="1.0" encoding="UTF-8& ...
- .Net Core导入千万级数据至Mysql
最近在工作中,涉及到一个数据迁移功能,从一个txt文本文件导入到MySQL功能. 数据迁移,在互联网企业可以说经常碰到,而且涉及到千万级.亿级的数据量是很常见的.大数据量迁移,这里面就涉及到一个问题 ...
- [在学习Django框架之前所需要了解的知识点]
[在学习Django框架之前所需要了解的知识点] Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现 ...
- [刷题] 279 Perfect Squares
要求 给出一个正整数n,寻找最少的完全平方数,使他们的和为n 示例 n = 12 12 = 4 + 4 + 4 输出:3 边界 是否可能无解 思路 贪心:12=9+1+1+1,无法得到最优解 图论:从 ...
- Ansible命令行方式执行
Ansible ad-hoc 什么是ad-hoc? 临时命令,执行完不会保存,类似于批量执行命令. ansible的选项 -i # 指定主机清单 ansible rsync -m ping -i 1. ...
- rsync+inotify实现全网自动化数据备份
第1章 环境配置 实例1-1 服务器及IP主机名规划 已知 4 台服务器主机名主机对应信息见下表: 服务器说明 外网 IP(NAT) 内网 IP(NAT) 主机名 web服务器 10.0.0.7/2 ...
- Modbus RTU CRC校验码计算方法
在CRC计算时只用8个数据位,起始位及停止位,如有奇偶校验位也包括奇偶校验位,都不参与CRC计算. CRC计算方法是: 1. 加载一值为0XFFFF的16位寄存器,此寄存器为CRC寄存器. 2. ...
- WIFF SD卡
https://detail.tmall.com/item.htm?spm=a230r.1.14.1.2d4d6923Fq3Hgx&id=36945441834&cm_id=14010 ...
- Linux 系统日志和系统信息常用命令介绍
日志文件 日 志 文 件 说 明 /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一 /var/log/secure 与安全相关的日志信息 / ...