线程到底有哪些状态?
    线程的状态要分来看,一种是操作系统线程,一种是jvm线程(本质上是对操作系统线程的封装)。

    操作系统线程状态:

    image.png
    jvm线程状态:
    image.png
    我们来看看jdk中Thread类下的状态枚举

    这里可能会觉得少了running状态,确实对于java线程来讲,runnable包括了就绪和运行。目前cpu进行抢占式执行,对时间片分配的单元一般在20ms左右,对如此短暂的时间进行状态切换没有必要。见【_ These states are virtual machine states which do not reflect 】

    1. /**
    2. * 线程的状态枚举,jvm线程一定会会处于一下状态之一
    3. * NEW - 线程没有开始(new Thread())
    4. * RUNNABLE - 线程在jvm中执行
    5. * BLOCKED - 线程等待监视器锁
    6. * WAITING - 线程无限等待另外一个线程的特定动作(wait -> notfiy, park -> unpark)
    7. * TIMED_WAITING - 线程等待另外一个线程的特定动作直到超时
    8. * TERMINATED - 线程终止
    9. * 这里的线程状态是指jvm线程,并不映射操作系统线程状态。
    10. */
    11. public enum Thread.State {
    12. /**
    13. * 线程没有开始
    14. */
    15. NEW,
    16. /**
    17. * 线程正在jvm中执行,但也可能在等待cpu资源,或者IO资源
    18. */
    19. RUNNABLE,
    20. /**
    21. * 线程在等待监视器锁,以便进入synchronized代码块
    22. * 或者是调用Object.wait方法后重新进入待synchronized代码块
    23. */
    24. BLOCKED,
    25. /**
    26. * 线程调用以下方法后处于等待状态:
    27. * Object.wait
    28. * Thread.join
    29. * LockSupport.park
    30. * 处于等待状态的线程需要另外一个线程的相关动作来触发,相应动作及状态变化如下:
    31. * Object.wait -> Object.notify(notifyAll)(WAITING -> BLOCKED)
    32. * Thread.join -> 目标线程终止(WAITING -> RUNNABLE)
    33. * LockSupport.park -> LockSupport.unpark(WAITING -> RUNNABLE)
    34. */
    35. WAITING,
    36. /**
    37. * 线程调用以下方法后处于有限时长的等待状态
    38. * 要么和WAITING一样被触发唤醒,要么超时时间达到唤醒(注意多了一个sleep)
    39. * Thread.sleep(long time)
    40. * Object.wait(long time)
    41. * Thread.join(long time)
    42. * LockSupport.parkNanos/parkUntil
    43. */
    44. TIMED_WAITING,
    45. /**
    46. * 线程退出
    47. */
    48. TERMINATED;
    49. }

    操作系统线程和jvm线程的状态是怎么对应的?

    操作系统线程 jvm线程
    NEW NEW
    RUNNABLE RUNNABLE
    RUNNING
    WAITING BLOCKED
    WAITING
    TIMED_WAITING
    TERMINATED TERMINATED
    类型 操作 操作系统线程 jvm线程 备注
    操作系统 read、write RUNNING -> WAITING RUNNABLE不变 由于操作系统线程让出cpu,所以对于jvm线程来说,处于却不会执行的RUNNABLE状态。
    jvm yield RUNNING -> RUNNABLE RUNNABLE不变
    sleep RUNNING -> WAITING RUNNING -> TIMED_WAITING
    wait RUNNING -> WAITING RUNNING -> WAITING
    synchronied RUNNING -> WAITING RUNNING -> BLOCKED



    什么情况下线程会发生切换?

    • 线程阻塞
    • 时间片轮转
    • 主动放弃时间

    线程切换的开销在哪里?
    线程切换时,必然需要将旧线程的task_struct从内核切出,将新线程的切入,带来上下文切换。除此之外,还需要切换寄存器、程序计数器、线程栈(包括操作栈、数据栈)等。