1、sleep()方法
    sleep()使当前线程进入停滞状态(阻塞当前线程),让出CUP的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会;
    sleep()是Thread类的Static(静态)的方法;因此他不能改变对象的机锁,所以当在一个Synchronized块中调用Sleep()方法是,线程虽然休眠了,但是对象的机锁并木有被释放,其他线程无法访问这个对象(即使睡着也持有对象锁)。
    在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。

2、wait()方法

    wait()方法是Object类里的方法;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池中,同时失去(释放)了对象的机锁(暂时失去机锁,wait(long timeout)超时时间到后还需要返还对象锁);其他线程可以访问;

wait()使用notify或者notifyAlll或者指定睡眠时间来唤醒当前等待池中的线程。

notify()和notifyAll()方法只是唤醒等待该对象的monitor(即锁)的线程,并不决定哪个线程能够获取到monitor(即锁)。

wait()必须放在synchronized block中,否则会在program runtime时抛出”java.lang.IllegalMonitorStateException“异常。

wait()方法在jdk文档中的解释如下:

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

3、所以sleep()和wait()方法的最大区别是:
    sleep()睡眠时,保持对象锁,仍然占有该锁;
    而wait()睡眠时,释放对象锁。
    但是wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException(但不建议使用该方法)。

实例1,使用sleep.

package com.lee.thread;public class SleepThread1 implements Runnable {int number = 10;public void firstMethod() throws Exception {synchronized (this) {number += 100;System.out.println(number);}}public void secondMethod() throws Exception {synchronized (this) {/*** (休息2S,阻塞线程) 以验证当前线程对象的机锁被占用时, 是否被可以访问其他同步代码块*/Thread.sleep(2000);    //1. 把2注释掉,使用sleep;//this.wait(2000);    //2. 把1注释掉,使用wait;number *= 200;}}@Overridepublic void run() {try {firstMethod();} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {SleepThread1 sleepThread1 = new SleepThread1();Thread thread = new Thread(sleepThread1);thread.start();sleepThread1.secondMethod();System.out.println("number="+sleepThread1.number);}
}

结果:

2100
number=2100

实例2,使用wait

package com.lee.thread;public class SleepThread1 implements Runnable {int number = 10;public void firstMethod() throws Exception {synchronized (this) {number += 100;System.out.println(number);}}public void secondMethod() throws Exception {synchronized (this) {/*** (休息2S,阻塞线程) 以验证当前线程对象的机锁被占用时, 是否被可以访问其他同步代码块*///Thread.sleep(2000);  //1. 把2注释掉,使用sleep;this.wait(2000);  //2. 把1注释掉,使用wait;number *= 200;}}@Overridepublic void run() {try {firstMethod();} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {SleepThread1 sleepThread1 = new SleepThread1();Thread thread = new Thread(sleepThread1);thread.start();sleepThread1.secondMethod();System.out.println("number="+sleepThread1.number);}
}

结果:

110
number=22000

我们来大致分析一下此段代码,main()方法中实例化ThreadTest并启动该线程,然后调用该线程的一个方法(secondMethod()),因为在主线程中调用方法,所以调用的普通方法secondMethod())会先被执行(但并不是普通方法执行完毕该对象的线程方法才执行,普通方法执行过程中,该线程的方法也会被执行,他们是交替执行的,只是在主线程的普通方法会先被执行而已),所以程序运行时会先执行secondMethod(),而secondMethod()方法代码片段中有synchronized block,因此secondMethod方法被执行后,该方法会占有该对象机锁导致该对象的线程方法一直处于阻塞状态,不能执行,直到secondeMethod释放锁;
使用Thread.sleep(2000)方法时,因为sleep在阻塞线程的同时,并持有该对象锁,所以该对象的其他同步线程(secondMethod())无法执行,直到synchronized block执行完毕(sleep休眠完毕),secondMethod()方法才可以执行,因此输出结果为number*200+100;
使用this.wait(2000)方法时,secondMethod()方法被执行后也锁定了该对象的机锁,执行到this.wait(2000)时,该方法会休眠2S并释当前持有的锁,此时该线程的同步方法会被执行(因为secondMethod持有的锁,已经被wait()所释放),因此输出的结果为:number+100;

为什么第二个number是22000呢,因为wait后,对number*200了,所以值改变了。

再举个简单的例子:假如有三个线程Thread1、Thread2和Thread3都在等待对象objectA的monitor,此时Thread4拥有对象objectA的monitor,当在Thread4中调用objectA.notify()方法之后,Thread1、Thread2和Thread3只有一个能被唤醒。注意,被唤醒不等于立刻就获取了objectA的monitor。假若在Thread4中调用objectA.notifyAll()方法,则Thread1、Thread2和Thread3三个线程都会被唤醒,至于哪个线程接下来能够获取到objectA的monitor就具体依赖于操作系统的调度了。再

  上面尤其要注意一点,一个线程被唤醒不代表立即获取了对象的monitor,只有等调用完notify()或者notifyAll()并退出synchronized块,释放对象锁后,其余线程才可获得锁执行。

下面看一个例子就明白了:

package com.lee.thread;public class WaitNotify {public static Object object = new Object();public static void main(String[] args) {Thread1 thread1 = new Thread1();Thread2 thread2 = new Thread2();thread1.start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}thread2.start();}static class Thread1 extends Thread {@Overridepublic void run() {synchronized (object) {try {object.wait();} catch (InterruptedException e) {}System.out.println("线程" + Thread.currentThread().getName()+ "获取到了锁");}}}static class Thread2 extends Thread {@Overridepublic void run() {synchronized (object) {object.notify();System.out.println("线程" + Thread.currentThread().getName()+ "调用了object.notify()");}System.out.println("线程" + Thread.currentThread().getName() + "释放了锁");}}
}

结果永远是

线程Thread-1调用了object.notify()
线程Thread-1释放了锁
线程Thread-0获取到了锁

Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,在阻塞队列那一篇博文中就讲述到了,阻塞队列实际上是使用了Condition来模拟线程间协作。

1、Condition是个接口,基本的方法就是await()和signal()方法;
    2、Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
    3、调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
    Conditon中的await()对应Object的wait();
    Condition中的signal()对应Object的notify();
    Condition中的signalAll()对应Object的notifyAll()。

转自:http://www.cnblogs.com/DreamSea/archive/2012/01/16/2263844.html

Condition实例见:http://www.cnblogs.com/dolphin0520/p/3920385.html

sleep和wait区别相关推荐

  1. RPC 笔记(01)— RPC概念、调用流程、RPC 与 Restful API 区别

    1. 基本概念 PRC 远程过程调用 Remote Procedure Call,其就是一个节点请求另外一个节点提供的服务.当两个物理分离的子系统需要建立逻辑上的关联时,RPC 是牵线搭桥的常见技术手 ...

  2. C++ 笔记(28)— C++ 中 NULL和 nullptr 的区别

    最近看公司代码的时候发现在判断指针是否为空的时候,有的时候用的是 NULL, 有的时候用的是 nullptr 感觉很奇怪,好奇心驱使我查了下两者的区别,发现还是有很多细节需要学习的. 1. NULL ...

  3. gcc 和 g++ 的联系和区别,使用 gcc 编译 c++

    GCC 编译器已经为我们提供了调用它的接口,对于 C 语言或者 C++ 程序,可以通过执行 gcc 或者 g++ 指令来调用 GCC 编译器. 实际使用中我们更习惯使用 gcc 指令编译 C 语言程序 ...

  4. Python2 与 Python3 区别

    Python2.x 与 Python3.x 区别 1. print 函数 Python2 中 print 是语句(statement),Python3 中 print 则变成了函数.在 Python3 ...

  5. Docker 入门系列(1)- 初识容器,镜像、容器、仓库的区别

    Docker 简介 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发 ...

  6. HTTP 协议入门 — (TCP/IP协议族、通信传输流、URI 与 URL 的区别、Cookie 状态管理、HTTP 支持的方法、状态码类别、HTTP 首部字段)

    TCP/IP协议族 在介绍 HTTP 协议之前,我们先对 TCP/IP 协议族有个大概的了解,TCP/IP 协议从上到下主要分为应用层.传输层.网络层和数据链路层,各层的主要功能如下表所示: 协议层 ...

  7. python二进制打开(rb)和文本格式打开(r)什么区别?

    使用 open() 函数以文本格式打开文件和以二进制格式打开文件,唯一的区别是对文件中换行符的处理不同. 在 Windows 系统中,文件中用 "\r\n" 作为行末标识符(即换行 ...

  8. python中__dict__与dir()区别

    前言 Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案. __dict__与dir()的区别: dir()是一个函数,返回的是list: _ ...

  9. java和C#面向对象的区别

    问题:C#中的构造函数和java的构造函数一样吗? 答: .net的项目中,写实体Entity属性时,经常会为每一个属性写一对get和set方法,在用到这个实体或是一个类时,通过new实例化一个对象, ...

  10. 判别模型和生成模型的区别

    20210703 https://www.zhihu.com/question/20446337 机器学习"判定模型"和"生成模型"有什么区别? 重点 http ...

最新文章

  1. 【每日一念经】算法岗面经,一万字面试经验你确定不看?
  2. [My B.S paper draft]我的本科答辩论文草稿
  3. TrinityCore3.3.5编译过程-官方指导-踩坑总结
  4. struts启动过滤器异常_面试必备:网关异常了怎么办?如何做全局异常处理?
  5. [JLOI2011]不重复数字
  6. java多线程必须掌握吗_多线程模式有什么作用(java多线程必须掌握的知识)
  7. 【qduoj - 纳新题】凑数题(恰好装满类0-1背包 或 母函数)
  8. 11下滑半个屏幕_努比亚发布手表手机:柔性屏幕,体积感人
  9. 【OJ】2020蓝桥杯模拟赛题解(Java语言描述)
  10. 有什么软件可以测试手机gprs,哪个软件可通过GPRS发信息啊?
  11. 【英语学习】【Level 07】U04 Rest and Relaxation L3 The finest hotel
  12. activiti创建子流程_OA流程图绘制指南
  13. 95-40-120-java.util.concurrent-线程-AbstractEventExecutor
  14. 因开源协议“大打出手”,AWS 宣布创建 Elasticsearch、Kibana 分支
  15. 读取excel内容在网页上显示出来
  16. SVG SMIL animation动画详解
  17. Apache Mahout的Taste基于Hadoop实现协同过滤推荐引擎的代码分析
  18. 马云,你不缺孩子,很多人叫你爸爸
  19. IT狂人第一至四季/全集The IT Crowd迅雷下载
  20. 懂球帝Android客户端WebView优化之路

热门文章

  1. 使用 Vue3 实现锚点组件
  2. 课堂派批量下载PDF
  3. 「GoTeam 招聘时间」蚂蚁集团 PaaS 平台开发专家(杭州、上海、成都)
  4. 计算机慢的解决方法,计算机速度慢的解决方法
  5. orchard mysql_最强的.NET开源CMS - Orchard使用说明
  6. linux lvm2,LVM2常见用法详解
  7. UI设计--大象无形
  8. Python 游戏编程之实现飞机大战(含源代码)
  9. Stata:聚类调整后的标准误-Cluster-SE
  10. 火狐浏览器(53.0.3),预览pdf下载资源包