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方法之间区别的更多相关文章

  1. jQuery的prop和attr方法之间区别

    JQuery.attr(): Get the value of an attribute for the first element in the set of matched elements. J ...

  2. jquery中使元素显示和隐藏方法之间的区别

    在实际的项目开发中,要使一个元素隐藏的方法有很多,比如css的多种属性和jquery的多种方法,虽然他们的作用都是使元素不可见,但是各个方法实现的原理是不一样的.下面主要介绍jquery各个元素隐藏方 ...

  3. 二.OC基础--1,对象的存储细节,2,#pragma mark指令,3,函数和对象方法的区别,4,对象和方法之间的关系 ,5.课堂习题

    1,对象的存储细节, 1. 当创建一个对象的时候:Person *p1 = [Person new],做了三件事情: 1,申请堆内存空间: 2,给实例变量初始化: 3,返回所申请空间的首地址; 2. ...

  4. 并查集类的c++封装,比較union_find algorithm四种实现方法之间的性能区别

    问题描写叙述: 在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.有一个联合-查找算法(union-find algorithm ...

  5. ThinkPHP的D方法和M方法的区别

    M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...

  6. jQuery中的.bind()、.live()和.delegate()之间区别分析

    jQuery中的.bind()..live()和.delegate()之间区别分析,学习jquery的朋友可以参考下.   DOM树   首先,可视化一个HMTL文档的DOM树是很有帮助的.一个简单的 ...

  7. Hibernate框架之get和load方法的区别

    我们在学习Hibernate框架时,经常会进行修改,删除操作,对于这些操作,我们都应该先加载对象,然后在执行或删除的操作,那么这里Hibernate提供了两种方法按照主键加载对象,也就是我要说的get ...

  8. Java线程中yield与join方法的区别

    长期以来,多线程问题颇为受到面试官的青睐.虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用.之前,我讨论了一个w ...

  9. M方法和D方法的区别

    M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...

随机推荐

  1. spring mvc简单使用

    spring mvc pom.xml依赖与插件 导入servlet.springmvc.Jackson的依赖,编译插件.tomcat <?xml version="1.0" ...

  2. JavaWeb——JDBC

    内容索引 1. JDBC基本概念 2. 快速入门 3. 对JDBC中各个接口和类详解 JDBC: 1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言 ...

  3. 逆向工程初步160个crackme-------1

    放假在家学习的效率真的很低,看完看雪加密解密的前两章就迫不及待的找了几个crackme练习一下,顺便熟悉ollydbg的使用. 工具:exeinfope(查壳工具),ollydbg(2.10版) 1. ...

  4. python爬虫——汽车之家数据

    相信很多买车的朋友,首先会在网上查资料,对比车型价格等,首选就是"汽车之家",于是,今天我就给大家扒一扒汽车之家的数据: 一.汽车价格: 首先获取的数据是各款汽车名称.价格范围以及 ...

  5. win10下卸载ubuntu的合理操作

    这里不推荐使用第三方软件,因为可能会被植入病毒,而且windows自带的命令行工具足以完成任务! win10系统自带的一个命令行工具--diskpart 在cmd中输入"diskpart&q ...

  6. DataGear 变更部署数据库为SQL Server填坑指南(含转写后的SQL server代码及SQL server配置文件)

    1. 引言 2. 配置数据库链接 3. 引入数据库驱动 4. 手动初始化数据库 5. 改写SQL 6. 其他 7. 参考 1. 引言 DataGear默认使用Derby数据库作为系统的元数据库,至于待 ...

  7. [刷题] 75 Sort Colors

    要求 给只有0 1 2三个元素的数组排序 思路 方法1:遍历数组,利用辅助数组保存三个元素的个数,再写入(遍历两遍) 辅助数组有三个元素,对应0 1 2的个数 方法2:模拟三路快排,遍历一遍完成排序 ...

  8. python从hello world开始(3)

    """# !usr/bin/env python# -*- coding:utf-8 _*-""""""@Au ...

  9. Ubuntu 获取升级信息失败。可能网络有问题

    升级Ubuntu系统时遇到的这个问题, 原因是默认的源不是国内的,而且还可能导致下载慢等问题. 1.备份源 cd /etc/apt/ sudo cp sources.list sources.list ...

  10. 【转】Spring_IOC学习

    原文地址:http://github.thinkingbar.com/spring/ 一.XML文件语法的知识点 对于XML没有提示的话,在Eclipse中搜索XML catalog设置.对于XML文 ...