`
dengzhangtao
  • 浏览: 667928 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java线程阻塞

阅读更多
线程阻塞是指一个线程的执行,在等待某个条件或者资源,在java中提供了很多方法来支持线程阻塞。

( 这里我先提一下,线程的阻塞是会让出cpu的!,在最后有简单的解释)
下面我逐一分析。

    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()
方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用
中我们应该灵活使用各种方法,以便更好地达到我们的目的。


这里先提一下,线程在阻塞时,会让出CPU,因为os的进程调度(或线程管理)程序会将你的线程冻结,将cpu给别的线程代码执行。

即使在线程中的执行是死循环。系统也会强迫它让出CPU给其它线程。只是当前线程的其它代码执行不了而已。
当然,如果你用的是buy-loop方式来等待别的线程的话, 就不会交出cpu了, 因为os的进程调度或者线程管理程序,不认为你的线程需要冻结。
0
2
分享到:
评论

相关推荐

    Java Socket学习---单线程阻塞

    NULL 博文链接:https://1358440610-qq-com.iteye.com/blog/2114621

    java线程阻塞中断与LockSupport使用介绍

    本文将详细介绍java线程阻塞中断和LockSupport的使用,需要了解更多的朋友可以参考下

    java 同步阻塞并唤醒指定线程

    java 多线程 同步阻塞 唤醒

    java多线程编程总结

    详细的讲述了多线程的各种用法 Java线程:概念与原理 ...Java线程:新特征-阻塞队列 Java线程:新特征-阻塞栈 Java线程:新特征-条件变量 Java线程:新特征-原子量 Java线程:新特征-障碍器 Java线程:大总结

    Java多线程编程总结

    Java 线程系列博文总结word化,编目如下,欢迎互相学习交流: ...Java线程:新特征-阻塞队列 Java线程:新特征-阻塞栈 Java线程:新特征-条件变量 Java线程:新特征-原子量 Java线程:新特征-障碍器

    java线程分析工具TDA

    分析java线程日志的工具,使用jstack把java线程日志dump下来,然后上传到该工具,就可以查看线程阻塞情况等信息。

    java模拟阻塞队列

    实现java模拟阻塞队列的例子,该代码包括,阻塞队列实现生产者,消费者。和模拟阻塞队列实现生产者及消费者模式,帮助你更好的理解java多线程

    Java 线程总结

    Java线程:概念与原理 Java线程:创建与启动 ...Java线程:新特征-阻塞队列 Java线程:新特征-阻塞栈 Java线程:新特征-条件变量 Java线程:新特征-原子量 Java线程:新特征-障碍器 Java线程:大总结

    java多线程经典案例

    java多线程经典案例,线程同步、线程通信、线程阻塞等经典案例

    深入理解Java线程编程中的阻塞队列容器

    阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。 阻塞队列提供了四种处理方法: 抛出异常...

    java线程详解

    Java线程:新特征-阻塞队列 Java线程:新特征-阻塞栈 Java线程:新特征-条件变量 Java线程:新特征-原子量 Java线程:新特征-障碍器 Java线程:深入ThreadLocal 一、标准例子 二、不用ThreadLocal 三、自己...

    java线程文档大全

    包含java线程的概念、原理、交互、合并、让步、守护、休眠、同步、锁以及新特性 锁 线程池 信号量 有返回值的线程 原子量 障碍器 阻塞列队和阻塞栈。java开发必备参考文档。

    Java中使用阻塞队列控制线程集实例

    主要介绍了Java控制阻塞队列线程集实例,本文用一个程序展示了如何使用阻塞队列来控制线程集,程序功能是在一个目录及它的所有子目录下搜索所有文件,打印出包含指定关键字的文件列表,需要的朋友可以参考下

    Java线程唤醒与阻塞常用方法共2页.pdf.zip

    Java线程唤醒与阻塞常用方法共2页.pdf.zip

    输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程

    通过ps到java进程号将进程的jstack信息输出。jstack信息是java进程的线程堆栈信息,通过该信息可以分析java的线程阻塞等问题。

    java中线程挂起的几种方式详解

    主要介绍了java中线程挂起的几种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    java线程学习笔记

    2.4 线程阻塞 17 2.4.1 调用sleep(millisecond)使任务进入休眠状态 17 2.4.2 等待输出与输入 17 2.4.3 对象锁不可用 17 2.4.4 通过wait()使线程挂起。 17 2.5 线程合作(wait || notifyAll) 21 2.5.1 Wait()两种...

    Java Socket学习---多线程阻塞

    NULL 博文链接:https://1358440610-qq-com.iteye.com/blog/2114632

Global site tag (gtag.js) - Google Analytics