线程的生命周期

线程的生命周期和状态

状态名称 说明
New 新创建
Runnable 可运行
Blocked 被阻塞
Waiting 等待
Timed_waiting 计时等待
Terminated 被终止
  • New 表示线程被创建但尚未启动的状态
    当我们用 new Thread() 新建一个线程时,如果线程没有开始运行 start() 方法,所以也没有开始执行 run() 方法里面的代码,那么此时它的状态就是 New ,而一旦线程调用了 start() 它的状态就会从 New 变成 Runnable
  • Runnable 可运行
    Java 中的 Runable 状态对应操作系统线程状态中的两种状态,分别是 Running 和 Ready
    Java 中处于 Runnable 状态的线程有可能正在执行,也有可能没有正在执行正在等待被分配 CPU 资源
  • 阻塞状态
    • Blocked(被阻塞)
      1. 从 Runnable 状态进入 Blocked 状态只有一种可能,就是进入 synchronized 保护的代码时没有抢到 monitor 锁 无论是进入 synchronized 代码块 还是 synchronized 方法,都是一样
      2. 从 Blocked 状态进入 Runnable 状态 要求线程获取 monitor 锁
    • Waiting(等待)
      • 线程进入 Waiting 状态有三种可能性:
        1. 没有设置 Timeout 参数的 Object.wait() 方法
        2. 没有设置 Timeout 参数的 Thread.join() 方法
        3. LockSupport.park() 方法
      • 从 Waiting 状态流转到其他状态则比较特殊
        如果其他线程调用 notify() 或 notifyAll()来唤醒它它会直接进入 Blocked 状态 因为唤醒 Waiting 线程的线程如果调用 notify() 或 notifyAll(),要求必须首先持有该 monitor 锁,所以处于 Waiting 状态的线程被唤醒时拿不 到该锁,就会进入 Blocked 状态
    • Timed Waiting(计时等待)
      • 线程进入 Timed Waiting 状态有四种可能性:
        1. 设置了时间参数的 Thread.sleep(long millis) 方 法
        2. 设置了时间参数的 Object.wait(long timeout) 方 法
        3. 设置了时间参数的 Thread.join(long millis) 方 法
        4. 设置了时间参数的 LockSupport.parkNanos(long nanos) 方法和LockSupport.parkUntil(long deadline) 方法
      • Timed Waiting 中执行 notify() 和 notifyAll() 也是一样的道理
        1. 如果其他线程调用 notify() 或 notifyAll()来唤 醒它它会直接进入 Blocked 状态
        2. 如果它的超时时间到了且能直接获取到锁/join的线程运行结束/被中断/调用了LockSupport.unpark(),会直接恢复到 Runnable 状态,而无需经历 Blocked 状态
    • Terminated 终止
      • 进入Terminated 终止状态有两种可能:
        1. run() 方法执行完毕,线程正常退出
        2. 出现一个没有捕获的异常,终止了 run() 方法,最终导致意外终止

注意点

  1. 线程的状态是需要按照箭头方向来走的,比如线程从 New 状态是不可以直接进入 Blocked 状态的,它需要先经历 Runnable 状态
  2. 线程生命周期不可逆:一旦进入 Runnable 状态就不能回到 New 状态;一旦被终止就不可能 再有任何状态的变化。所以一个线程只能有一次 New 和 Terminated 状态,只有处于中间状 态才可以相互转换

wait/notify和sleep的异同

  • 相同点:
    1. 它们都可以让线程阻塞
    2. 它们都可以响应 interrupt 中断,在等待的过程中如果收到中断信号,都可以进行响应, 并抛出 InterruptedException 异常
  • 不同点:
    1. wait 方法必须在 synchronized 保护的代码中使用,而 sleep 方法并没有这个要求
    2. 在同步代码中执行 sleep 方法时,并不会释放 monitor 锁,但执行 wait 方法时会主动 释放 monitor 锁
    3. sleep 方法中会要求必须定义一个时间,时间到期后会主动恢复,而对于没有参数的 wait 方法而言,意味着永久等待,直到被中断或被唤醒才能恢复,它并不会主动恢复
    4. wait/notify 是 Object 类的方法,而 sleep 是 Thread 类的方法

你可能感兴趣的:(线程的生命周期)