阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一

定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。

转载于:http://blog.csdn.net/small____fish/article/details/7726468

  1. sleep() 方法:sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间

内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。

  典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后

重新测试,直到条件满足为止。

  2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会

自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和 

resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个

线程产生了结果后,调用 resume() 使其恢复。

  3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于

可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足

够的时间从而转到另一个线程。

  4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式

,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或

者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。

  初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区

别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则

相反。



  上述的核心区别导致了一系列的细节上的区别。



  首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,

所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞

时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象

上的锁被释放。而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随

机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。



  其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块

中调用,理由也很简单,只有在synchronized 方法或块中当前线程才占有锁,才有锁可以释放。同样的

道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调

用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若

不满足这一条件,则程序虽然仍能编译,但在运行时会出现 IllegalMonitorStateException 异常。



  wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和

操作系统的进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作

系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语

(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间

通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。



  关于 wait() 和 notify() 方法最后再说明两点:

  第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随

机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问

题。



  第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 

notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有

获得锁的那一个线程才能进入可执行状态。

  谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 

方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小

心地避免死锁。



  以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify() 

方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用

中我们应该灵活使用各种方法,以便更好地达到我们的目的。

总结:

wait和notify、notifyall方法属于Object类,它们涉及到锁的释放问题,所以和synchronized关键字一起使用。

suspend() 和 resume() 方法配套使用。

Java线程唤醒与阻塞的更多相关文章

  1. 简单测试Java线程安全中阻塞同步与非阻塞同步性能

    摘抄自周志明老师的<深入理解Java虚拟机:JVM高级特性与最佳实践>13.2.2 线程安全的实现方法 1.名词解释 同步是指锁哥线程并发访问共享数据时,保证共享数据同一时刻只被一个线程访 ...

  2. Java线程--BlockingQueue使用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871704.html Java线程--BlockingQueue使用 阻塞队列就是内容满了之 ...

  3. 多线程之Java线程阻塞与唤醒

    线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题.如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节.在Java ...

  4. java - 线程等待与唤醒

    Java多线程系列--“基础篇”05之 线程等待与唤醒 概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. w ...

  5. 面试官:都说阻塞 I/O 模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?

    摘要: 原创出处 https://studyidea.cn 「公众号:程序通事 」欢迎关注和转载,保留摘要,谢谢! 使用 Java 阻塞 I/O 模型读取数据,将会导致线程阻塞,线程将会进入休眠,从而 ...

  6. 一天十道Java面试题----第三天(对线程安全的理解------>线程池中阻塞队列的作用)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 21.对线程安全的理解 22.Thread和Runnable的区别 23.说说你对守护线程的理解 24.ThreadLoc ...

  7. java线程自带队列的使用以及线程阻塞

    java线程,设置队列的大小实现队列阻塞 public class QueueThreads { private static int nThreads = 4;//Runtime.getRuntim ...

  8. 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue

    从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.ThreadPoolExecutor 就是这样的线程池.以下是我的学习过程. 首先是构 ...

  9. java线程(7)——阻塞队列BlockingQueue

    回顾: 阻塞队列,英文名叫BlockingQueue.首先他是一种队列,联系之前Java基础--集合中介绍的Queue与Collection,我们就很容易开始今天的阻塞队列的学习了.来看一下他们的接口 ...

随机推荐

  1. QuantLib 金融计算——收益率曲线之构建曲线(1)

    目录 QuantLib 金融计算--收益率曲线之构建曲线(1) YieldTermStructure DiscountCurve DiscountCurve 对象的构造 ZeroCurve ZeroC ...

  2. IntelliJ IDEA 18 周岁,吐血推进珍藏已久的必装插件

    IntelliJ IDEA是目前最好最强最智能的Java IDE,前几天,他刚刚年满18岁.  本文,给大家推荐几款我私藏已久的,自己经常使用的,可以提升代码效率的插件. IDEA插件简介 常见的I ...

  3. win10 安装 mysql 5.7

    win10 安装 mysql 5.7 1.在mysql 官网下载mysql 5.7 的手动安装包 mysql--winx64.zip 2. 解压到mysql 目录的文件夹下面 D:\moudle\my ...

  4. 【实战】JBOSS反序列化Getshell

    一.JBOSS4.0.5_GA,5.x,6.x 需要JavaDeserH2HC(https://github.com/joaomatosf/JavaDeserH2HC) 操作起来 javac -cp ...

  5. js数字动画

    项目中需要的数字动画效果,网上找不到需要的效果,所以自己写了一个. 不多说,直接上干货:

  6. (转)GlusterFS 01 理论基础,企业实战,故障处理

    https://jaminzhang.github.io/glusterfs/GlusterFS-01-Theory-Basis/--------GlusterFS 01 理论基础 https://j ...

  7. 机器学习 损失函数(Loss/Error Function)、代价函数(Cost Function)和目标函数(Objective function)

    损失函数(Loss/Error Function): 计算单个训练集的误差,例如:欧氏距离,交叉熵,对比损失,合页损失 代价函数(Cost Function): 计算整个训练集所有损失之和的平均值 至 ...

  8. Java时间的使用

    JAVA处理日期时间常用方法: 1.java.util.Calendar Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR.MONTH.DAY_OF_MONTH.HOUR 等 日历字 ...

  9. [转]NancyFx/Nancy

    本文转自:https://github.com/NancyFx/Nancy/wiki/Documentation Getting Started Introduction Exploring the ...

  10. Angular2-三种样式封装策略的区别

    Angular2有三种样式封装方式,分别是None.Native.Emulated. 可用元数据“encapsulation”配置,配置方式如下: encapsulation: ViewEncapsu ...