线程的生命周期(状态转换)

概述

一个线程只能处于一种状态,并且这里的线程状态特指 Java 虚拟机的线程状态,不能反映线程在特定操作系统下的状态。

线程在⽣命周期中并不是固定处于某⼀个状态⽽是随着代码的执⾏在不同状态之间切换。Java线程状态变迁如下图所示(图源《Java 并发编程艺术》4.1.4 节):
在这里插入图片描述

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。 在线程的生命周期中,它要经过6 种状态(

意不是5种状态,具体参照源码可知)。尤其是当线程启动以后,它不可能一直"霸占"着CPU独自运行,所以CPU需要在多条线程之间切

换,于是线程状态也会多次在运行、阻塞之间切换。

1.初始状态 (New)

当程序使用 new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由 JVM为其分配内存,并初始化其成员变量的值。

新创建了一个线程对象,但还没有调用start()方法。

2.运行状态 (Runnable)

Java线程中将就绪(Ready)和运行中(Running)两种状态笼统的称为“运行”。

线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获

取CPU的使用权,此时处于就绪状态(Ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(Running)。

2.1 就绪状态(Ready)
  • 就绪状态只是说你资格运行,调度程序没有挑选到你,你就永远是就绪状态。
  • 调用线程的start()方法,此线程进入就绪状态。
  • 当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。
  • 当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。
  • 锁池里的线程拿到对象锁后,进入就绪状态。
2.2 运行中状态

线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一的一种方式。

3.阻塞状态(Blocked)

表示线程阻塞于锁。

这个状态下,是在多个线程有同步操作的场景,比如正在等待另一个线程的 synchronized 块的执行释放,或者可重入的 synchronized

块里别人调用 wait() 方法,也就是线程在等待进入临界区。

2.1等待阻塞(o.wait->等待对列)

运行(running)的线程执行 o.wait()方法,JVM会把该线程放入等待队列(waitting queue) 中。

2.2同步阻塞(lock->锁池)

运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM会把该线 程放入锁池(lock pool)中。

2.3其他阻塞(sleep/join)

运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法,或者发出了 I/O请求时, JVM会把该线程置为阻塞状态。当 sleep()状态

超时、join()等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入可运行(runnable)状态。

4.无限期等待状态(Waiting)

进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。

处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。

进入方法退出方法
没有设置 Timeout 参数的 Object.wait() 方法Object.notify() / Object.notifyAll()
没有设置 Timeout 参数的 Thread.join() 方法被调用的线程执行完毕
LockSupport.park() 方法-

5.限期等待状态(Timed_Waiting)

处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。

调用 Thread.sleep() 方法使线程进入限期等待状态时,常常用 “使一个线程睡眠” 进行描述。

调用 Object.wait() 方法使线程进入限期等待或者无限期等待时,常常用 “挂起一个线程” 进行描述。

睡眠和挂起是用来描述行为,而阻塞等待用来描述状态

阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁。而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方

法进入。

进入方法退出方法
Thread.sleep() 方法时间结束
设置了 Timeout 参数的 Object.wait() 方法时间结束 / Object.notify() / Object.notifyAll()
设置了 Timeout 参数的 Thread.join() 方法时间结束 / 被调用的线程执行完毕
LockSupport.parkNanos() 方法-
LockSupport.parkUntil() 方法-

6.终止状态(Terminated)

线程会以下面三种方式终止,终止后就是死亡状态。

1.正常结束: run() 或 call()方法执行完成,线程正常结束。

2.异常结束: 线程抛出一个未捕获的 Exception或 Error。

3.调用stop: 直接调用该线程的 stop()方法来结束该线程—该方法通常容易导致死锁,不推荐使用

注:对网上知识点的简单总结,感谢大家批评指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值