Java 几种线程状态之间的相互关系

简介: Java Doc 里通过一个枚举类型 Enum<Thread.State> 来定义。

Java Thread 可能处在以下几种状态


Java Doc 里通过一个枚举类型 Enum<Thread.State> 来定义。

线程可以处于以下状态之一:

3@3_RCQ5K`BTO}`F$7[3UQ2.png

  • NEW 尚未启动的线程处于此状态。
  • RUNNABLE 在Java虚拟机中执行的线程处于此状态。
  • BLOCKED 被阻塞等待监视器锁定的线程处于此状态。
  • WAITING 无限期等待另一个线程执行特定操作的线程处于此状态。
  • TIMED_WAITING 正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。
  • TERMINATED 已退出的线程处于此状态。

线程在给定时间点只能处于一种状态。这些状态是虚拟机状态,不反映任何操作系统线程状态。

通过示例而不是Java doc中给出的正式定义,可以很容易地理解任何令人困惑的概念。如果它们是现实生活中的例子,它可能更具有相关性。我想分享一些可能有助于理解这些线程状态的现实例子。

[GO1P}I)H%FWC3WOONZB(PY.png

http://fastthread.io 生成的传递图,显示哪些线程阻塞了哪些线程


BLOCKED 阻塞


Java doc正式将BLOCKED状态定义为:“阻塞等待监视器锁的线程处于此状态。”

现实生活中的例子:今天你要去面试。这是您梦寐以求的工作,这是您过去几年一直瞄准的目标。你早上醒来,准备好了,穿上你最好的衣服,在镜子前面看起来很敏锐。现在你走出你的车库,意识到你的妻子已经开车了。在这种情况下,你只有一辆车,那么会发生什么?在现实生活中,可能会发生斗争:-)。在这里你被阻止,因为你的妻子已经开车了。你将无法参加面试。

这是BLOCKED状态。用技术术语解释它,你是线程T1,你的妻子是线程T2,锁是汽车。T1在锁(即汽车)上被阻挡,因为T2已经获得了这个锁。

提示:线程在等待监视器锁进入同步块/方法或在调用Object#wait()方法后重新输入同步块/方法时,将进入BLOCKED状态。


WAITING 等候


Java doc正式将WAITING状态定义为:“无限期等待另一个线程执行特定操作的线程处于此状态。”

现实生活中的例子:让我们说几分钟后你的妻子带着车回家了。现在你意识到面试的时间已经到了,而且到达那里还有很长的路要走。因此,您将所有动力都放在汽车的油门踏板上。当允许的速度限制仅为60英里/小时时,您以100英里/小时的速度行驶。你不走运,交通警察看到你超过限速,他把你拉到路边。现在你进入WAITING状态,我的朋友。你停止开车,坐在车里闲逛,直到警察调查你,然后让你走。基本上,在他让你离开之前,你会陷入等待状态。

用技术术语解释它,你是线程T1,警察是线程T2。你释放锁(即你停止开车),然后进入等待状态。直到警察(即T2)让你离开,你将陷入这种等待状态。

提示:线程在调用以下方法之一时将进入WAITING状态:

  • Object#wait() 未指定超时时间
  • Thread#join() 未指定超时时间
  • LockSupport#park()

在对象上调用Object.wait()的线程处于WAITING状态,直到另一个线程调用该对象上的Object.notify()或Object.notifyAll()。调用Thread.join()的线程处于WAITING状态,以使指定的线程终止。


TIMED_WAITING 指定时间的等待


Java doc正式将TIMED_WAITING状态定义为:“等待另一个线程在指定的等待时间内执行操作的线程处于此状态。”

现实生活中的例子: 尽管所有的戏剧性,你在采访中表现得非常好,给每个人留下了深刻的印象并得到了这份高薪工作。(恭喜!)你回到家里,告诉你的邻居关于这份新工作,以及你对此感到非常兴奋。你的朋友说他也在同一栋办公楼工作。他建议你们两个应该一起开车。你认为这是一个好主意。所以在工作的第一天,你去他家。你把车停在他家门口。你等了10分钟,但你的邻居仍然没有出来。你继续开始上班,因为你不想在第一天被推迟。现在这是TIMED_WAITING。

用技术术语解释它,你是线程T1,你的邻居是线程T2。你释放锁定(即停止驾驶汽车)并等待长达 10分钟。如果你的邻居T2在10分钟内没出来,你就开始再次开车了。

提示:线程在调用以下方法之一时将进入TIMED_WAITING状态:

  • Thread#sleep()
  • Object#wait() 指定超时时间
  • Thread#join() 指定超时时间
  • LockSupport#parkNanos()
  • LockSupport#parkUntil()


结论


当有人在分析线程转储时,理解这些不同的线程状态是至关重要的。处于RUNNABLE,BLOCKED,WAITING和TIMED_WATING状态的线程数是多少?哪些线程被阻止?谁阻止了他们?用于锁定的对象是什么?这些是在线程转储中要分析的一些重要指标。这些详细的线程转储分析可以通过在线工具轻松完成,例如:http://fastthread.io/

相关文章
|
27天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
85 17
|
2月前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
22天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
2月前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
2月前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
2月前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
63 3
|
2月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
189 2
|
2月前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
56 6
|
3月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
2月前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####