首页 > 编程语言 >Java多线程:状态转移详解

Java多线程:状态转移详解

时间:2023-12-27 10:36:59浏览次数:39  
标签:状态 超时 Java Thread 详解 线程 多线程 等待 运行

Java中的线程在其生命周期内会经历不同的状态。理解这些状态以及它们之间的转换对于掌握多线程编程至关重要。本文将详细介绍Java线程的状态以及它们之间的转换机制。

线程生命周期状态

根据Java语言规范和java.lang.Thread.State枚举定义,线程的状态主要分为以下几种:

  • 新建(NEW):创建后尚未启动的线程处于此状态。
  • 可运行(RUNNABLE):处于可运行状态的线程正在Java虚拟机中运行,但它可能正在等待来自操作系统的资源,如处理器。
  • 阻塞(BLOCKED):线程等待监视器锁(进入一个synchronized块/方法)以进入同步代码区域时,它会进入此状态。
  • 等待(WAITING):线程因为调用Object.wait()Thread.join()LockSupport.park()而处于等待状态,需要其他线程显式唤醒。
  • 超时等待(TIMED_WAITING):类似于等待状态,但有最大等待时间,线程在指定的时间后会被自动唤醒,或可通过Thread.interrupt()等方法提前唤醒。
  • 终止(TERMINATED):线程正常完成执行或因异常退出而终止。

状态转移

线程状态之间的转移由Java运行时环境控制,也受到线程自身的行为和其他线程的影响。

1. 新建到可运行

当线程被创建,即实例化Thread类的对象后,它处于新建状态。调用线程对象的start()方法后,线程进入可运行状态。在这个状态下,线程可能正在执行,也可能在等待操作系统分配执行时间。

Thread thread = new Thread(() -> {
    // Code to execute
});
thread.start(); // 线程进入可运行状态

2. 可运行与阻塞的转换

当线程试图获取一个锁以进入一个同步区域,但锁被其他线程持有时,它会从可运行状态变成阻塞状态。当持有锁的线程释放锁后,阻塞状态的线程会重新进入可运行状态。

synchronized(lock) {
    // 当前线程持有锁,其他试图进入这个块的线程会阻塞
}

3. 可运行与等待/超时等待的转换

线程可以通过调用Object.wait()Thread.join()LockSupport.park()等方法主动进入等待状态。通过调用Object.wait(long timeout)Thread.sleep(long millis)等方法,它可以进入超时等待状态。线程在这些状态下不会执行任何操作,直到被唤醒或超时。

synchronized(obj) {
    obj.wait(); // 线程进入等待状态,直到另一个线程在该对象上调用notify()/notifyAll()
}
Thread.sleep(1000); // 纑程进入超时等待状态,直到时间到或线程被中断

4. 等待/超时等待到可运行的转换

线程在等待状态下,需要其他线程调用相应对象的notify()notifyAll()LockSupport.unpark(Thread thread)方法将其唤醒。对于超时等待状态,线程会在等待时间结束后自动变为可运行状态,或可以被其他线程提前唤醒。

synchronized(obj) {
    obj.notify(); // 唤醒在该对象上等待的一个线程
}

5. 终止

线程在完成了它的执行任务后,或者因为异常退出,进入终止状态。一旦线程终止,它的状态不会再发生变化。

public void run() {
    // Code
    // 执行完成后,线程进入终止状态
}

线程状态的重要性

了解线程状态对于编写可靠和高效的多线程程序至关重要。例如,死锁可能发生在多个线程互相等待对方释放锁的情况下,造成它们都无法进入可运行状态。另外,不恰当的状态管理可能导致线程饥饿、过度竞争和性能问题。

实践建议:

  • 避免不必要的锁,以减少线程进入阻塞状态的机会。
  • 合理使用等待/通知机制,确保线程能够在适当的时候被唤醒。
  • 避免长时间的超时等待,因为这可能导致系统资源的浪费。
  • 监控线程状态,了解系统运行时线程的实际状态,以便进行调优和排查问题。

通过理解和掌握线程状态及其转换,我们可以编写出更稳定、响应更快的Java多线程应用程序。

标签:状态,超时,Java,Thread,详解,线程,多线程,等待,运行
From: https://blog.51cto.com/u_16351957/8995791

相关文章

  • 【Java核心基础】一文带你了解Java中构造方法的重要作用!
    构造方法是Java中用于初始化对象状态的特殊方法,与类同名且无返回类型,创建对象时自动调用,可重载以提供灵活性;若未定义,编译器提供默认构造方法,它可加访问修饰符,可用super()调用父类构造方法,构造方法不可继承或直接调用,可用于依赖注入。定义在Java中,构造方法专门负责初始化新创......
  • 无涯教程-Java加密 - 获取密钥
    在本章中,无涯教程将学习如何使用Java密码术从密钥库中检索密钥。要从密钥库中检索密钥,请遵循以下步骤。步骤1-创建KeyStore对象java.security包的KeyStore类的getInstance()方法接受一个表示密钥库类型的字符串值,并返回一个KeyStore宾语。如下所示,使用此方法创建KeyS......
  • Java实现单例模式
    饿汉式静态常量饿汉式的优点是:在类装载的时候就完成实例化,没有达到LazyLoading的效果,并且避免了线程同步问题。它的缺点是:如果从始至终从未使用过这个实例,则会造成内存的浪费。publicclassadaDemo3{publicstaticvoidmain(String[]args){Singletonins......
  • Unity3D 如何提升游戏运行效率详解
    Unity3D是一款非常强大的游戏引擎,但是在处理复杂场景和大量资源时,游戏运行效率可能会遇到一些问题。本文将详细介绍如何提升Unity3D游戏的运行效率,包括技术详解和代码实现。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术......
  • Unity3D 项目中怎样正确的使用 Lua详解
    在Unity3D游戏开发中,Lua作为一种轻量级的脚本语言,被广泛应用于游戏逻辑的编写和扩展。本文将详细介绍如何正确地在Unity3D项目中使用Lua,并给出相应的技术详解和代码实现。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬......
  • Unity3D Asset与Object 资源管理系统详解
    Unity3D是一款流行的游戏开发引擎,它提供了一个强大的资源管理系统,可以帮助开发者有效地管理和使用游戏中的资源。在Unity3D中,资源可以分为Asset和Object两种类型,本文将详细介绍Unity3D的Asset与Object资源管理系统的技术细节和代码实现。对啦!这里有个游戏开发交流小组里面聚集了......
  • java中属性和变量的区别与final和抽象类
    属性和变量的区别变量必须要有初始值;属性可以没有初始值;变量的范围只在当前大括号内有效;属性是对象在哪里使用就在哪里有效;属性的作用范围要比变量的大一些属性和变量publicclassstudy01{ publicstaticvoidmain(String[]args){ //这是一个变量Stringnam......
  • 无涯教程-Java9 - @Deprecated增强
    @Deprecated注释是在Java5版本中引入的。用@Deprecated注释的程序元素表示,由于以下任何原因,不建议使用它-其用法可能会导致错误。它在将来的版本中可能不被兼容。它在将来的版本中可能会被删除。一个更好,更高效的替代方法取代了它。每当使用不推荐使用的元素时,编译器都会......
  • java 8 的新特性(三)
    java8新的日期时间APIJava8引入了一个新的日期时间API,也称为java.timeAPI,以替代旧的java.util.Date和java.util.Calendar类。这个新API提供了更清晰、更强大和更易于使用的日期和时间功能。Java8的日期时间API包括以下部分:日期和时间类型:包括LocalDate(日期),LocalTime(时间),LocalDa......
  • 混合专家模型 (MoE) 详解
    随着Mixtral8x7B(announcement,modelcard)的推出,一种称为混合专家模型(MixedExpertModels,简称MoEs)的Transformer模型在开源人工智能社区引起了广泛关注。在本篇博文中,我们将深入探讨MoEs的核心组件、训练方法,以及在推理过程中需要考量的各种因素。让我们开始吧!......