线程包括哪些状态,状态之间是如何变化?
创始人
2025-07-07 18:01:12
0

1. 线程状态-六种状态

线程的状态可以参考JDK中的Thread类中的枚举State,存在六种状态

public enum State {
//尚未启动的线程的线程状态
  NEW,

  //可运行线程的线程状态
  RUNNABLE,

//线程阻塞等待监视器锁的线程状态
  BLOCKED,

//等待线程的线程状态
  WAITING,

//具有指定等待时间的等待线程的线程状态(有限等待)
  TIMED_WAITING,

 //已终止线程的线程状态。线程已完成执行
  TERMINATED;
}

六种状态介绍:

新建(NEW)

  • 当一个线程对象被创建,但还未调用 start 方法时处于新建状态
  • 此时未与操作系统底层线程关联

可运行(RUNNABLE):

  • 调用了 start 方法,就会由新建进入可运行
  • 此时与底层线程关联,由操作系统调度执行

终结(TERMINATED)

  • 线程内代码已经执行完毕,由可运行进入终结
  • 此时会取消与底层线程关联

阻塞(BLOCKED)

  • 当获取锁失败后,由可运行进入 Monitor 的阻塞队列阻塞,此时不占用 cpu 时间
  • 当持锁线程释放锁时,会按照一定规则唤醒阻塞队列中的阻塞线程,唤醒后的线程进入可运行状态

等待(WAITING)

  • 当获取锁成功后,但由于条件不满足,调用了 wait() 方法,此时从可运行状态释放锁进入 Monitor 等待集合等待,同样不占用 cpu 时间
  • 当其它持锁线程调用 notify() 或 notifyAll() 方法,会按照一定规则唤醒等待集合中的等待线程,恢复为可运行状态

有时限等待(TIMED_WAITING)

  • 当获取锁成功后,但由于条件不满足,调用了 wait(long) 方法,此时从可运行状态释放锁进入 Monitor 等待集合进行有时限等待,同样不占用 cpu 时间
  • 当其它持锁线程调用 notify() 或 notifyAll() 方法,会按照一定规则唤醒等待集合中的有时限等待线程,恢复为可运行状态,并重新去竞争锁
  • 如果等待超时,也会从有时限等待状态恢复为可运行状态,并重新去竞争锁
  • 还有一种情况是调用 sleep(long) 方法也会从可运行状态进入有时限等待状态,但与 Monitor 无关,不需要主动唤醒,超时时间到自然恢复为可运行状态

其它情况(只需了解)

  • 可以用 interrupt() 方法打断等待、有时限等待的线程,让它们恢复为可运行状态
  • park,unpark 等方法也可以让线程等待和唤醒

2. 线程状态-五种状态

五种状态的说法来自于操作系统层面的划分

  • 运行态:分到 cpu 时间,能真正执行线程内代码的
  • 就绪态:有资格分到 cpu 时间,但还未轮到它的
  • 阻塞态:没资格分到 cpu 时间的
  1. 涵盖了 java 状态中提到的阻塞等待有时限等待
  2. 多出了阻塞 I/O,指线程在调用阻塞 I/O 时,实际活由 I/O 设备完成,此时线程无事可做,只能干等
  • 新建与终结态:与 java 中同名状态类似,不再啰嗦

3. wait和sleep方法的不同?

共同点

wait() ,wait(long) 和 sleep(long) 的效果都是让当前线程暂时放弃 CPU 的使用权,进入阻塞状态

不同点

1.方法归属不同

  • sleep(long) 是 Thread 的静态方法
  • 而 wait(),wait(long) 都是 Object 的成员方法,每个对象都有 醒来时机不同
  • 执行 sleep(long) 和 wait(long) 的线程都会在等待相应毫秒后醒来
  • wait(long) 和 wait() 还可以被 notify 唤醒,wait() 如果不唤醒就一直等下去
  • 它们都可以被打断唤醒

2.锁特性不同(重点)

  • wait 方法的调用必须先获取 wait 对象的锁,而 sleep 则无此限制
  • wait 方法执行后会释放对象锁,允许其它线程获得该对象锁(我放弃 cpu,但你们还可以用)
  • 而 sleep 如果在 synchronized 代码块中执行,并不会释放对象锁(我放弃 cpu,你们也用不了)
3. 线程状态面试题

面试官:线程包括哪些状态,状态之间是如何变化的?

候选人:

在JDK中的Thread类中的枚举State里面定义了6中线程的状态分别是:新建、可运行、终结、阻塞、等待和有时限等待六种。

关于线程的状态切换情况比较多。我分别介绍一下:

当一个线程对象被创建,但还未调用 start 方法时处于新建状态,调用了 start 方法,就会由新建进入可运行状态。如果线程内代码已经执行完毕,由可运行进入终结状态。当然这些是一个线程正常执行情况。

如果线程获取锁失败后,由可运行进入 Monitor 的阻塞队列阻塞,只有当持锁线程释放锁时,会按照一定规则唤醒阻塞队列中的阻塞线程,唤醒后的线程进入可运行状态。

如果线程获取锁成功后,但由于条件不满足,调用了 wait() 方法,此时从可运行状态释放锁等待状态,当其它持锁线程调用 notify() 或 notifyAll() 方法,会恢复为可运行状态。

还有一种情况是调用 sleep(long) 方法也会从可运行状态进入有时限等待状态,不需要主动唤醒,超时时间到自然恢复为可运行状态。


相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...