Java高并发第35篇:线程6种状态详解

star2017 1年前 ⋅ 522 阅读

线程的状态有哪几种?他们之间是如何转换的?

目录

1、线程状态分类

线程一共有六种状态,分别为New、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED,同一时刻只有一种状态,通过线程的getState方法可以获取线程的状态。

2、状态详解

Thread的状态使用java.lang.Thread.State枚举表示。

2.1、状态1:NEW

当线程被创建出来还没有被调用start()时候的状态。

  1. public class NewState {
  2. public static void main(String[] args) {
  3. Thread thread1 = new Thread("thread1");
  4. System.out.println(thread1.getState());
  5. }
  6. }

输出

  1. NEW

2.2、状态2:RUNNABLE

当线程被调用了start(),且处于等待操作系统分配资源(如CPU)、等待IO连接、正在运行状态,即表示Running状态和Ready状态。

注:不一定被调用了start()立刻会改变状态,还有一些准备工作,这个时候的状态是不确定的。

  1. public class RunnableState {
  2. public static void main(String[] args) {
  3. Thread thread1 = new Thread("thread1");
  4. thread1.start();
  5. System.out.println(thread1.getState());
  6. }
  7. }

输出

  1. RUNNABLE

2.3、状态3:BLOCKED

等待监视器锁而被阻塞的线程的线程状态,当进入synchronized块/方法或者在调用wait()被唤醒/超时之后重新进入synchronized块/方法,但是锁被其它线程占有,这个时候被操作系统挂起,状态为阻塞状态。

阻塞状态的线程,即使调用interrupt()方法也不会改变其状态。

下面看案例代码,thread1持有lock对象的锁一直没有释放,而thread2也想获取lock对象的锁,但是锁一直被thread1持有者,导致thread2被阻塞在@1处,此时thread2的状态就是BLOCKED状态。

  1. import java.util.concurrent.TimeUnit;
  2. public class BlockedState {
  3. static String lock = "锁";
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread thread1 = new Thread("thread1") {
  6. @Override
  7. public void run() {
  8. synchronized (lock) {
  9. //死循环导致thread1一直持有lock对象锁
  10. while (true) ;
  11. }
  12. }
  13. };
  14. thread1.start();
  15. //休眠1秒,让thread1先启动
  16. TimeUnit.SECONDS.sleep(1);
  17. Thread thread2 = new Thread("thread2") {
  18. @Override
  19. public void run() {
  20. synchronized (lock) { //@1
  21. System.out.println("thread2");
  22. }
  23. }
  24. };
  25. thread2.start();
  26. System.out.println("thread1.state:" + thread1.getState());
  27. System.out.println("thread2.state:" + thread2.getState());
  28. }
  29. }

运行结果

  1. thread1.state:RUNNABLE
  2. thread2.state:BLOCKED

2个线程的堆栈信息,线程堆栈信息中包含了线程的详细信息,如:线程状态、线程目前执行到哪段代码了

  1. "thread2" #13 prio=5 os_prio=0 tid=0x00000000281ec000 nid=0x878 waiting for monitor entry [0x0000000028dff000]
  2. java.lang.Thread.State: BLOCKED (on object monitor)
  3. at BlockedState$2.run(BlockedState.java:25)
  4. - waiting to lock <0x00000007176b2a20> (a java.lang.String)
  5. Locked ownable synchronizers:
  6. - None
  7. "thread1" #12 prio=5 os_prio=0 tid=0x00000000281ea800 nid=0x5e50 runnable [0x0000000028cff000]
  8. java.lang.Thread.State: RUNNABLE
  9. at BlockedState$1.run(BlockedState.java:12)
  10. - locked <0x00000007176b2a20> (a java.lang.String)
  11. Locked ownable synchronizers:
  12. - None

2.4、状态4:WAITING

无条件等待,当线程调用wait()/join()/LockSupport.park()不加超时时间的方法之后所处的状态,如果没有被唤醒或等待的线程没有结束,那么将一直等待,当前状态的线程不会被分配CPU资源和持有锁.

简单理解:就是无限期等待。

导致线程处于WAITING有3中方式。

方式1:wait()

  1. import java.util.concurrent.TimeUnit;
  2. public class WaitingState1 {
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread thread1 = new Thread("thread1") {
  5. @Override
  6. public void run() {
  7. synchronized (WaitingState1.class) {
  8. try {
  9. //调用wait方法,让线程等待
  10. WaitingState1.class.wait();
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. }
  16. };
  17. thread1.start();
  18. //模拟休眠1秒,让thread1运行到wait方法处
  19. TimeUnit.SECONDS.sleep(1);
  20. System.out.println("thread.state:" + thread1.getState());
  21. }
  22. }

输出

  1. thread1.state:WAITING

线程thread1堆栈信息

  1. "thread1" #12 prio=5 os_prio=0 tid=0x0000000027a5d800 nid=0x1b48 in Object.wait() [0x0000000028dbe000]
  2. java.lang.Thread.State: WAITING (on object monitor)
  3. at java.lang.Object.wait(Native Method)
  4. - waiting on <0x00000007176adc68> (a java.lang.Class for WaitingState1)
  5. at java.lang.Object.wait(Object.java:502)
  6. at WaitingState1$1.run(WaitingState1.java:11)
  7. - locked <0x00000007176adc68> (a java.lang.Class for WaitingState1)
  8. Locked ownable synchronizers:
  9. - None

方式2:join()

  1. public class WaitingState2 {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread thread1 = new Thread("thread1") {
  4. @Override
  5. public void run() {
  6. while (true) ;
  7. }
  8. };
  9. thread1.start();
  10. //join方法会让当前主线程等待thread1结束
  11. thread1.join();
  12. }
  13. }

上面代码会导致主线程处于WAITING状态,下面是主线程堆栈信息,第2行显示主线程处于WAITING状态

  1. "main" #1 prio=5 os_prio=0 tid=0x00000000035a4000 nid=0x3fbc in Object.wait() [0x000000000305f000]
  2. java.lang.Thread.State: WAITING (on object monitor)
  3. at java.lang.Object.wait(Native Method)
  4. - waiting on <0x00000007176b0708> (a WaitingState2$1)
  5. at java.lang.Thread.join(Thread.java:1249)
  6. - locked <0x00000007176b0708> (a WaitingState2$1)
  7. at java.lang.Thread.join(Thread.java:1323)
  8. at WaitingState2.main(WaitingState2.java:14)
  9. Locked ownable synchronizers:
  10. - None

方式3:LockSupport.park()

  1. import java.util.concurrent.TimeUnit;
  2. import java.util.concurrent.locks.LockSupport;
  3. public class WaitingState3 {
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread thread1 = new Thread("thread1") {
  6. @Override
  7. public void run() {
  8. LockSupport.park();
  9. }
  10. };
  11. thread1.start();
  12. //模拟休眠1秒,让thread1运行到park方法处
  13. TimeUnit.SECONDS.sleep(1);
  14. System.out.println("thread1.state:" + thread1.getState());
  15. }
  16. }

输出

  1. thread1.state:WAITING

线程thread1堆栈信息

  1. "thread1" #12 prio=5 os_prio=0 tid=0x00000000287cc000 nid=0x3880 waiting on condition [0x000000002918f000]
  2. java.lang.Thread.State: WAITING (parking)
  3. at sun.misc.Unsafe.park(Native Method)
  4. at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
  5. at WaitingState3$1.run(WaitingState3.java:9)
  6. Locked ownable synchronizers:
  7. - None

2.5、状态5:TIMED_WAITING

有条件的等待,当线程调用sleep(睡眠时间)/wait(等待时间)/join(等待时间)/ LockSupport.parkNanos(等待时间)/LockSupport.parkUntil(等待时间)方法之后所处的状态,在指定的时间没有被唤醒或者等待线程没有结束,会被系统自动唤醒,正常退出。

简单点理解:有限期等待。

导致线程处于WAITING有5中方式。

方式1:sleep(睡眠时间)

  1. import java.util.concurrent.TimeUnit;
  2. public class TimedWaitingState1 {
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread thread1 = new Thread("thread1") {
  5. @Override
  6. public void run() {
  7. //休眠500秒 = 500000毫秒
  8. try {
  9. Thread.sleep(500 * 1000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. };
  15. thread1.start();
  16. //模拟休眠1秒,让thread1运行到sleep方法处
  17. TimeUnit.SECONDS.sleep(1);
  18. System.out.println("thread1.state:" + thread1.getState());
  19. }
  20. }

输出

  1. thread1.state:TIMED_WAITING

线程thread1堆栈信息,堆栈信息中可以看出是线程sleep方法导致线程等待的

  1. "thread1" #12 prio=5 os_prio=0 tid=0x0000000027e1c000 nid=0x5c68 waiting on condition [0x000000002917f000]
  2. java.lang.Thread.State: TIMED_WAITING (sleeping)
  3. at java.lang.Thread.sleep(Native Method)
  4. at TimedWaitingState1$1.run(TimedWaitingState1.java:10)
  5. Locked ownable synchronizers:
  6. - None

方式2:wait(等待时间)

  1. import java.util.concurrent.TimeUnit;
  2. public class TimedWaitingState2 {
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread thread1 = new Thread("thread1") {
  5. @Override
  6. public void run() {
  7. synchronized (TimedWaitingState2.class) {
  8. try {
  9. //调用wait方法,让线程等待500秒
  10. TimedWaitingState2.class.wait(500 * 1000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. }
  16. };
  17. thread1.start();
  18. //模拟休眠1秒,让thread1运行到wait方法处
  19. TimeUnit.SECONDS.sleep(1);
  20. System.out.println("thread1.state:" + thread1.getState());
  21. }
  22. }

输出

  1. thread1.state:TIMED_WAITING

线程thread1堆栈信息,堆栈信息中可以看出是线程wait方法导致线程等待的

  1. "thread1" #12 prio=5 os_prio=0 tid=0x0000000028571000 nid=0x4b80 in Object.wait() [0x0000000028f2e000]
  2. java.lang.Thread.State: TIMED_WAITING (on object monitor)
  3. at java.lang.Object.wait(Native Method)
  4. - waiting on <0x00000007176ae0b8> (a java.lang.Class for TimedWaitingState2)
  5. at TimedWaitingState2$1.run(TimedWaitingState2.java:11)
  6. - locked <0x00000007176ae0b8> (a java.lang.Class for TimedWaitingState2)
  7. Locked ownable synchronizers:
  8. - None

方式3:join(等待时间)

  1. public class TimedWaitingState3 {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread thread1 = new Thread("thread1") {
  4. @Override
  5. public void run() {
  6. while (true) ;
  7. }
  8. };
  9. thread1.start();
  10. //join方法会让当前主线程等待thread1结束,最长等待500s,如果500s
  11. thread1.join(500 * 1000);
  12. }
  13. }

主线程堆栈信息

  1. "main" #1 prio=5 os_prio=0 tid=0x0000000003274000 nid=0x1204 in Object.wait() [0x00000000030ee000]
  2. java.lang.Thread.State: TIMED_WAITING (on object monitor)
  3. at java.lang.Object.wait(Native Method)
  4. - waiting on <0x00000007176b0cf8> (a TimedWaitingState3$1)
  5. at java.lang.Thread.join(Thread.java:1257)
  6. - locked <0x00000007176b0cf8> (a TimedWaitingState3$1)
  7. at TimedWaitingState3.main(TimedWaitingState3.java:11)
  8. Locked ownable synchronizers:
  9. - None

方式4:LockSupport.parkNanos(等待时间)

  1. import java.util.concurrent.TimeUnit;
  2. import java.util.concurrent.locks.LockSupport;
  3. public class TimedWaitingState4 {
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread thread1 = new Thread("thread1") {
  6. @Override
  7. public void run() {
  8. //等待500秒
  9. LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(500));
  10. }
  11. };
  12. thread1.start();
  13. //模拟休眠1秒,让thread1运行到parkNanos方法处
  14. TimeUnit.SECONDS.sleep(1);
  15. System.out.println("thread1.state:" + thread1.getState());
  16. }
  17. }

输出

  1. thread1.state:TIMED_WAITING

线程thread1堆栈信息

  1. "thread1" #12 prio=5 os_prio=0 tid=0x0000000028a1e000 nid=0x455c waiting on condition [0x00000000293ff000]
  2. java.lang.Thread.State: TIMED_WAITING (parking)
  3. at sun.misc.Unsafe.park(Native Method)
  4. at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)
  5. at TimedWaitingState4$1.run(TimedWaitingState4.java:10)
  6. Locked ownable synchronizers:
  7. - None

方式5:LockSupport.parkUntil(等待时间)

  1. import java.util.concurrent.TimeUnit;
  2. import java.util.concurrent.locks.LockSupport;
  3. public class TimedWaitingState5 {
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread thread1 = new Thread("thread1") {
  6. @Override
  7. public void run() {
  8. //等待500秒
  9. LockSupport.parkUntil(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(500));
  10. }
  11. };
  12. thread1.start();
  13. //模拟休眠1秒,让thread1运行到parkNanos方法处
  14. TimeUnit.SECONDS.sleep(1);
  15. System.out.println("thread1.state:" + thread1.getState());
  16. }
  17. }

输出

  1. thread1.state:TIMED_WAITING

线程thread1堆栈信息

  1. "thread1" #12 prio=5 os_prio=0 tid=0x00000000291b2000 nid=0x3cc0 waiting on condition [0x0000000029b8f000]
  2. java.lang.Thread.State: TIMED_WAITING (parking)
  3. at sun.misc.Unsafe.park(Native Method)
  4. at java.util.concurrent.locks.LockSupport.parkUntil(LockSupport.java:372)
  5. at TimedWaitingState5$1.run(TimedWaitingState5.java:10)
  6. Locked ownable synchronizers:
  7. - None

2.6、状态6:TERMINATED

执行完了run()方法。其实这只是Java语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求,而在Java语言级别只是通过Java代码看到的线程状态而已。

  1. import java.util.concurrent.TimeUnit;
  2. public class TerminatedState {
  3. public static void main(String[] args) throws InterruptedException {
  4. Thread thread1 = new Thread("thread1") {
  5. @Override
  6. public void run() {
  7. System.out.println(Thread.currentThread());
  8. }
  9. };
  10. thread1.start();
  11. //休眠1秒,等待thread1执行完毕
  12. TimeUnit.SECONDS.sleep(1);
  13. System.out.println("thread1 state:" + thread1.getState());
  14. }
  15. }

输出

  1. Thread[thread1,5,main]
  2. thread1 state:TERMINATED

3、状态转换图

这个图是本文的重点,反复看,消化理解!!!

4、阿里最新版《Java 开发手册》

java 开发者必读的手册,阿里最新版《Java 开发规范》来了,本手册是阿里巴巴集团技术团队的集体智慧结晶和经验总结,愿景是码出高效, 码出质量。

获取方式,扫码发送:阿里

最新资料

更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: