操作系统

操作系统 层面来描述的
线程状态 - 图1

  • 【初始状态】仅是在语言层面创建了线程对象,还未与操作系统线程关联
  • 【可运行状态】(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度执行
  • 【运行状态】指获取了 CPU 时间片运行中的状态
    • 当 CPU 时间片用完,会从【运行状态】转换至【可运行状态】,会导致线程的上下文切换
  • 【阻塞状态】
    • 如果调用了阻塞 API,如 BIO 读写文件,这时该线程实际不会用到 CPU,会导致线程上下文切换,进入【阻塞状态】
    • 等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
    • 与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们
  • 【终止状态】表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态

    Java API

    Java API 层面来描述的
    image.png

  • NEW线程刚被创建,但是还没有调用 start() 方法

  • RUNNABLE 当调用了 start() 方法之后,注意,Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的
  • 【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为是可运行 RUNNING)
  • BLOCKED , WAITING , TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分,后面会在状态转换一节详述
  • TERMINATED 当线程代码运行结束
  1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  2. 运行(RUNNABLE):Java线程中将就绪(ready)运行中(running)两种状态笼统的称为“运行”。
    线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
  3. 阻塞(BLOCKED):表示线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。

    线程的状态图

    线程状态 - 图3 ```java package cn.itcast.n3;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

@Slf4j(topic = “c.TestState”) public class TestState { public static void main(String[] args) throws IOException { // t1线程没有调用start方法,所以线程状态是NEW Thread t1 = new Thread(“t1”) { @Override public void run() { log.debug(“running…”); } };

  1. // t2线程陷入死循环,一直处于运行,分到了时间片,或者没有分到时间片,陷入了CPU的IO阻塞,这些情况都属于RUNNABLE
  2. Thread t2 = new Thread("t2") {
  3. @Override
  4. public void run() {
  5. while(true) { // runnable
  6. }
  7. }
  8. };
  9. t2.start();
  10. // t3线程顺利执行完毕,该线程的状态是TERMINATED
  11. Thread t3 = new Thread("t3") {
  12. @Override
  13. public void run() {
  14. log.debug("running...");
  15. }
  16. };
  17. t3.start();
  18. // t4线程等待睡眠,线程的状态变为TIMED_WAITING
  19. Thread t4 = new Thread("t4") {
  20. @Override
  21. public void run() {
  22. synchronized (TestState.class) {
  23. try {
  24. Thread.sleep(1000000); // timed_waiting
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. };
  31. t4.start();
  32. // t5线程调用t2线程,等待t2线程运行结束,就会导致t5一直等待,因为没有加时限,不会被CPU任务调度,该线程状态是WAITING
  33. Thread t5 = new Thread("t5") {
  34. @Override
  35. public void run() {
  36. try {
  37. t2.join(); // waiting
  38. } catch (InterruptedException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. };
  43. t5.start();
  44. // t6线程加了锁,而t4线程先进行了加锁,所以t6拿不到这个对象的锁,最后被阻塞住了,状态是BLOCKED
  45. Thread t6 = new Thread("t6") {
  46. @Override
  47. public void run() {
  48. synchronized (TestState.class) { // blocked
  49. try {
  50. Thread.sleep(1000000);
  51. } catch (InterruptedException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }
  56. };
  57. t6.start();
  58. try {
  59. Thread.sleep(500);
  60. } catch (InterruptedException e) {
  61. e.printStackTrace();
  62. }
  63. log.debug("t1 state {}", t1.getState());
  64. log.debug("t2 state {}", t2.getState());
  65. log.debug("t3 state {}", t3.getState());
  66. log.debug("t4 state {}", t4.getState());
  67. log.debug("t5 state {}", t5.getState());
  68. log.debug("t6 state {}", t6.getState());
  69. System.in.read();
  70. }

} ```