Java中的线程状态(详见Java线程状态及转换-MarchOn):

  • wait:Object类的实例方法,释放CPU执行权,进入等待状态,直到  被中断、被拥有该对象锁的线程唤醒(notify或notifyAll)、wait时间到了自己唤醒 三者之一发生。会释放所持有的对象锁。(关于 wait、notiy、notifyAll的配合原理见后面

示例:wait()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在获得对象锁后执行即在 synchronized函数或synchronized block中进行调用,否则如果虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

  1. package buaa.act.ucar.imtg.main;
  2.  
  3. /**
  4. * @author zsm
  5. * @date 2017年3月3日 上午10:23:53
  6. */
  7. public class Test extends Thread {
  8. public static void main(String[] args) {
  9. // TODO Auto-generated method stub
  10. Test test = new Test();
  11. test.start();
  12. try {
  13. synchronized (test) {
  14. Thread.sleep(1000);
  15. System.out.println("wake the thread in main...");
  16. test.isFire = true;
  17. test.notify();
  18. }
  19.  
  20. } catch (InterruptedException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. }
  24. }
  25.  
  26. /**
  27. * 线程锁
  28. */
  29. private final Object object = new Object();
  30.  
  31. private volatile boolean isFire = false;
  32.  
  33. @Override
  34. public void run() {
  35. System.out.println("开始执行线程。。。");
  36. System.out.println("进入等待状态。。。");
  37. synchronized (this) {
  38. try {
  39. while (!isFire) {
  40. wait();
  41. }
  42. } catch (InterruptedException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. System.out.println("线程结束。。。");
  47. }
  48. }
  • sleep:Thread类的静态方法,释放CPU执行权,等待指定时间后自己醒来。不会释放所持有对象的锁。
  • join:Thread实例的方法,释放CPU执行权,等待被调用join方法的线程结束才继续执行本线程下面的操作。不会释放所持有对象的锁。
  • interrupt:1、打断处于等待状态的线程(对于阻塞状态的线程不起作用,如因synchronized方法或代码块等而阻塞的线程):在wait或sleep的线程、在等待线程结束的线程(join的调用者)可以被中断(叫打断更贴切,fuck翻译),如果被中断,会抛出InterruptedException;2、对非等待状态的线程调用interrupt不会抛异常,需要手动检测线程状态并做相应处理。

两个示例:

  1. //打断处于等待状态的线程
  2. public class InterruputSleepThread {
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread t1 = new Thread() {
  5. @Override
  6. public void run() {
  7. //while在try中,通过异常中断就可以退出run循环
  8. try {
  9. while (true) {
  10. //当前线程处于阻塞状态,异常必须捕捉处理,无法往外抛出
  11. TimeUnit.SECONDS.sleep(2);
  12. }
  13. } catch (InterruptedException e) {
  14. System.out.println("Interruted When Sleep");
  15. boolean interrupt = this.isInterrupted();
  16. //中断状态被复位
  17. System.out.println("interrupt:"+interrupt);
  18. }
  19. }
  20. };
  21. t1.start();
  22. TimeUnit.SECONDS.sleep(2);
  23. //中断处于阻塞状态的线程
  24. t1.interrupt();
  25.  
  26. /**
  27. * 输出结果:
  28. Interruted When Sleep
  29. interrupt:false
  30. */
  31. }
  32. }
  33.  
  34. //对处于运行状态的线程标记中断
  35. public class InterruputThread {
  36. public static void main(String[] args) throws InterruptedException {
  37. Thread t1=new Thread(){
  38. @Override
  39. public void run(){
  40. while(true){
  41. //判断当前线程是否被中断
  42. if (this.isInterrupted()){
  43. System.out.println("线程中断");
  44. break;
  45. }
  46. }
  47.  
  48. System.out.println("已跳出循环,线程中断!");
  49. }
  50. };
  51. t1.start();
  52. TimeUnit.SECONDS.sleep(2);
  53. t1.interrupt();
  54.  
  55. /**
  56. * 输出结果:
  57. 线程中断
  58. 已跳出循环,线程中断!
  59. */
  60. }
  61. }
  62.  
  63. //阻塞状态的线程打断无效
  64. public class SynchronizedBlocked implements Runnable{
  65.  
  66. public synchronized void f() {
  67. System.out.println("Trying to call f()");
  68. while(true) // Never releases lock
  69. Thread.yield();
  70. }
  71.  
  72. /**
  73. * 在构造器中创建新线程并启动获取对象锁
  74. */
  75. public SynchronizedBlocked() {
  76. //该线程已持有当前实例锁
  77. new Thread() {
  78. public void run() {
  79. f(); // Lock acquired by this thread
  80. }
  81. }.start();
  82. }
  83. public void run() {
  84. //中断判断
  85. while (true) {
  86. if (Thread.interrupted()) {
  87. System.out.println("中断线程!!");
  88. break;
  89. } else {
  90. f();
  91. }
  92. }
  93. }
  94.  
  95. public static void main(String[] args) throws InterruptedException {
  96. SynchronizedBlocked sync = new SynchronizedBlocked();
  97. Thread t = new Thread(sync);
  98. //启动后调用f()方法,无法获取当前实例锁处于等待状态
  99. t.start();
  100. TimeUnit.SECONDS.sleep(1);
  101. //中断线程,无法生效
  102. t.interrupt();
  103. }
  104. }
  • yield:Thread的静态方法,此方法只是使当前线程重新回到可执行状态,不会阻塞线程,因此执行yield()的线程有可能在进入到可执行状态后马上又被执行。实际上,当某个线程调用了yield方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行的机会。
  • suspend:已过时,弃用
  • resume:已过时,弃用
  • stop:已过时,弃用

wait、notify、notifyAll三者的异同:(可参阅 彻底理解wait、notify、notifyAll)假设有对象A,线程T

  • 是Object类的实例方法,且是native方法
  • T调用A的这些方法时必须先拥有A的对象锁,即只能在同步方法或同步块中调用这些方法。否则会抛出IllegalMonitorStateException(是RuntimeException故无需try catch)
  • 调用wait方法并不是立马释放锁,要等同步方法或同步块执行完;同理,调用notify、notifyAll并不会有线程立马获取到对象锁,需要等调用者所在同步方法或同步块执行完。
  • 可以理解为每个对象有个wait set(等待池)和monitor set(锁池)用来存放线程:wait set中线程等待收到通知信号(notify、notifyAll)、不会竞争获取A的对象锁,而monitor set中的线程则竞争对象锁;T调用A的wait方法则T进入wait set、T调用notify或notifyAll则wait set中的一个线程(随机选)或所有线程进入monitor set竞争对象锁。(从这可看出,第一个获得对象锁的wait线程执行完后,若没有继续调用该对象的notify或notifyAll,且monitor set中没有线程,则其他wait线程仍一直等待,即便对该对象锁已经空闲)

Java线程状态及 wait、sleep、join、interrupt、yield等的区别的更多相关文章

  1. Java线程状态Jstack线程状态BLOCKED/TIMED_WAITING/WAITING解释

    一.线程5种状态 新建状态(New) 新创建了一个线程对象. 就绪状态(Runnable) 线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运行,等待获 ...

  2. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

  3. 浅谈 Java线程状态转换及控制

    线程的状态(系统层面) 一个线程被创建后就进入了线程的生命周期.在线程的生命周期中,共包括新建(New).就绪(Runnable).运行(Running).阻塞(Blocked)和死亡(Dead)这五 ...

  4. Java线程状态及切换

    Java线程状态及切换 一.什么是Java线程状态 在Java程序中,用于描述Java线程的六种状态: 新建(NEW):当前线程,刚刚新建出来,尚未启动. 运行(RUNNABLE):当前线程,处于竞争 ...

  5. Java线程状态介绍

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11867086.html Java 线程状态介绍: Java官方文档中对Java线程的几种状态做 ...

  6. java线程中的sleep/wait/notify/yield/interrupt方法 整理

    java线程中的sleep/wait/notify/yield/interrupt方法 sleep 该方法能够使当前线程休眠一段时间 休眠期间,不释放锁 休眠时间结束之后,进入可执行状态,加入到线程就 ...

  7. Java线程状态转换

    前言:对于Java线程状态方面的知识点,笔者总感觉朦朦胧胧,趁着最近整理资料,将Java线程状态方面的知识点总结归纳,以便加深记忆. 1.Java线程状态值 在Thread类源码中通过枚举为线程定义了 ...

  8. Java线程状态切换以及核心方法

    1.Java线程状态 1.1 线程主要状态 ①初始(NEW):新创建了一个线程对象,但还没有调用start()方法.②运行(RUNNABLE):Java线程中将就绪(ready)和运行中(runnin ...

  9. 从源码看java线程状态

    关于java线程状态,网上查资料很混乱,有的说5种状态,有的说6种状态,初学者搞不清楚这个线程状态到底是怎么样的,今天我讲一下如何看源码去解决这个疑惑. 直接上代码: public class Thr ...

随机推荐

  1. IOS7 新特性

    相关ios7新特性 帖子.挺全的.一定要看看哪 http://www.devdiv.com/iOS_iPhone-ios_ui_uikit_text_kit_-thread-203631-1-1.ht ...

  2. 用visualbox虚拟机安装ubuntu

    用visualbox虚拟机安装ubuntu 哥的电脑原来要装双系统.结果电脑死了,磁盘格式化了.什么盘符又挺混乱.后来说用虚拟机装系统安全,又開始摸索. 我的电脑因之前的缘故,VMware软件用不了, ...

  3. MyEclipse中设置jsp页面为默认utf-8编码

    转自:http://www.cnblogs.com/xdp-gacl/p/3496161.html 在MyEclispe中创建Jsp页面,Jsp页面的默认编码是“ISO-8859-1”,如下图所示: ...

  4. LeetCode 326 Power of Three(3的幂)(递归、Log函数)

    翻译 给定一个整型数,写一个函数决定它是否是3的幂(翻译可能不太合适-- 跟进: 你能否够不用不论什么循环或递归来完毕. 原文 Given an integer, write a function t ...

  5. Socket网络编程--Libev库学习(2)

    这一小节讲各个观察器(Watcher) 在libev下面watcher相当于EventHandler这么一个概念,通常里面会绑定fd回调函数以及我们需要关注的事件. 然后一旦触发事件之后会触发我们使用 ...

  6. EditText: 自定义EditText 触摸时无法获取焦点

    写了一个自定义View,继承EditText,但是在触摸时无法获取到焦点. 在XML中添加 android:focusableInTouchMode="true" 设置触摸时可以获 ...

  7. [SQL in Azure] High Availability and Disaster Recovery for SQL Server in Azure Virtual Machines

    http://msdn.microsoft.com/en-us/library/azure/jj870962.aspx Microsoft Azure virtual machines (VMs) w ...

  8. Spring和Mybatis整合过程中遇到的一个找不到sqlSessionFactory或sqlSessionTemplate的异常

    先看启动web项目时IDEA控制台抛出的异常(红色部分): D:\tomcat-kafka-\bin\catalina.bat run [-- ::,] Artifact Gradle : com.x ...

  9. error: insufficient permissions for device(解决adb shell问题)

    今天在linux下连接平板usb,试用adb shell时出现error: insufficient permissions for device, 而且我们输入adb devices显示: xxna ...

  10. OpenSUSE安装软件

    zypper se xxxxx 是搜索软件包 zypper in xxxxx 跟你的apt-get install xxxx等价 zypper rm xxxx 删除 zypper up xxxx 更新 ...