【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态

简介: 【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态

本文讲解了 Java 中 三态和五态的概念,介绍了新建、运行、状态、阻塞、等待、计时等待状态的应用场景,并给出了样例代码。三态/五态是一种简化的描述,实际中线程可能会在不同的状态之间转换。

一、什么是三态

在 Java 多线程编程中,三态 是指线程的三种状态,包括以下三个状态,请同学们认真学习。

  1. 新建状态:当通过实例化 Thread 类或者创建 Runnable 接口的实现类对象时,线程处于新建状态。此时线程对象被创建,但还没有调用 start() 方法启动线程。
  2. 运行状态:当线程对象调用 start() 方法后,线程进入运行状态。此时线程会执行其 run() 方法中的代码。在运行状态下,线程可能会被操作系统抢占,也可能会主动放弃 CPU 的执行权。
  3. 阻塞状态:当线程正在运行时,可能因为某些原因暂时无法继续执行,进入阻塞状态。常见的阻塞原因包括等待 I/O 操作、等待获取锁等。在阻塞状态下,线程会暂停执行,直到阻塞的原因解除。

此外,还有一个特殊的状态,请同学们注意。

  • 终止状态:当线程的 run() 方法执行完毕或者调用了 Thread 类的 stop() 方法后,线程进入终止状态,终止状态的线程不再具有运行和阻塞的能力,它被称为 死亡

三态是一种简化的描述,实际中线程可能会在不同的状态之间转换。例如,当处于运行状态的线程调用了 sleep() 方法后,会进入阻塞状态;当等待的I/O操作完成后,阻塞的线程会再次进入运行状态。线程状态的转换由操作系统和 Java 运行时环境自动管理,开发人员可以通过调用线程的方法来控制线程的状态转换。


二、什么是五态

在 Java 多线程编程中,五态包括以下 5 55 个状态,请同学们认真学习。

  1. 新建状态:当通过实例化 Thread 类或者创建 Runnable 接口的实现类对象时,线程处于新建状态。此时线程对象被创建,但还没有调用 start() 方法启动线程。
  2. 运行状态:当线程对象调用 start() 方法后,线程进入运行状态。此时线程会执行其 run() 方法中的代码。在运行状态下,线程可能会被操作系统抢占,也可能会主动放弃 CPU 的执行权。
  3. 阻塞状态:当线程正在运行时,可能因为某些原因暂时无法继续执行,进入阻塞状态。常见的阻塞原因包括等待 I/O 操作、等待获取锁等。在阻塞状态下,线程会暂停执行,直到阻塞的原因解除。
  4. 等待状态:线程进入等待状态是因为调用了某些等待方法,如调用了 Object 类的 wait() 方法或者 Thread 类的 join() 方法。在等待状态下,线程会暂停执行,并且释放占用的锁资源,直到被其他线程唤醒。
  5. 计时等待状态:线程进入计时等待状态是因为调用了某些计时等待方法,如调用了 Thread 类的 sleep() 方法或者 Object 类的 wait(long timeout) 方法。与等待状态类似,线程会暂停执行,并且释放占用的锁资源,但是在指定的时间后会自动唤醒。

以上五态是对于普通线程的描述,对于守护线程来说,还有一个特殊的状态:

  • 终止状态:当线程的 run() 方法执行完毕或者调用了 Thread 类的 ·stop()· 方法后,线程进入终止状态,终止状态的线程不再具有运行和阻塞的能力,它被称为 死亡

线程状态的转换由操作系统和 JVM 自动管理,开发人员可以通过调用线程的方法来控制线程的状态转换。


三、五态之间如何转变

在 Java 中,线程的状态是由 JVM 和操作系统自动管理的,开发人员无法直接控制状态的转换

不过,我们可以通过调用线程的不同方法来触发状态的转换,以下是线程状态之间的一些常见转换示例,请同学们认真学习。

  1. 新建状态 -> 运行状态:通过调用线程对象的 start() 方法启动线程,线程会从新建状态转变为运行状态。
  2. 运行状态 -> 阻塞状态:线程可能会因为等待 I/O 操作、等待获取锁或调用了 Thread 类的 sleep() 方法等原因进入阻塞状态。
  3. 运行状态 -> 等待状态:线程调用了 Object 类的 wait() 方法,或者 Thread 类的 join() 方法等待其他线程的完成,进入等待状态。
  4. 运行状态 -> 计时等待状态:线程调用了Thread类的sleep(long millis)方法,或者 **Object** 类的wait(long timeout)` 方法,线程会在指定时间后自动唤醒,进入计时等待状态。
  5. 运行状态 -> 终止状态:线程的 run() 方法执行完毕,或者调用了 Thread 类的 stop() 方法,线程进入终止状态。

线程的状态转换是由 JVM 和操作系统负责管理的,开发人员无法直接控制和预测线程状态的转换。因此,在编写多线程程序时,同学们需要正确处理线程的状态转换,避免潜在的并发问题和死锁情况。

以下是一些 Java 线程五态转换的示例代码,请同学们复制到本地执行。

3.1 新建状态转换到运行状态

Thread thread = new Thread(() -> {
    // 线程执行的任务
});
thread.start(); // 启动线程,线程从新建状态转换为运行状态

3.2 运行状态转换到阻塞状态

public class MyRunnable implements Runnable {
    private Object lock;
    public MyRunnable(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        synchronized (lock) {
            // 临界区代码
            try {
                Thread.sleep(1000); // 线程休眠,进入阻塞状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread thread1 = new Thread(new MyRunnable(lock));
        Thread thread2 = new Thread(new MyRunnable(lock));
        thread1.start();
        thread2.start();
    }
}

3.3 运行状态转换到等待状态

public class MyRunnable implements Runnable {
    private Object lock;
    public MyRunnable(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        synchronized (lock) {
            try {
                lock.wait(); // 线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread thread = new Thread(new MyRunnable(lock));
        thread.start();
    }
}

3.4 运行状态转换到计时等待状态

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(2000); // 线程休眠,进入计时等待状态
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

3.5 运行状态转换到终止状态

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程执行的任务
    }
}
public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        // 等待线程执行完毕,线程从运行状态转换为终止状态
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

以上是一些常见的 Java 线程五态转换的示例代码,通过触发不同的方法或操作来实现状态之间的转换。在实际应用中,同学们需要根据具体的需求和情况灵活使用线程的不同状态来实现并发编程的目标。


四、五态的应用场景

Java 中线程的五态可以在不同的应用场景下发挥作用,以下是一些常见的应用场景,请同学们认真学习。

  1. 新建状态:在创建线程对象后,但还未调用 start() 方法之前的状态。这个状态适用于线程准备工作,例如为线程分配资源、初始化变量等。
  2. 运行状态:线程被启动后进入的状态,线程正在执行 run() 方法中的任务。在并发编程中,可以利用多个运行状态的线程同时执行不同的任务,提高系统的吞吐量和响应性。
  3. 阻塞状态:线程因为某些原因无法执行,进入阻塞状态。这个状态适用于等待外部资源、等待锁或者等待其他线程完成某些操作的情况。例如,当线程需要访问共享资源时,如果该资源已经被其他线程占用,当前线程就会进入阻塞状态,直到资源被释放。
  4. 等待状态:线程调用了 Object 类的 wait() 方法或者 Thread 类的 join() 方法,进入等待状态。这个状态适用于线程间的协调和通信。例如,一个线程等待其他线程完成某些操作后再继续执行。
  5. 计时等待状态:线程调用了 Thread 类的 sleep(long millis) 方法或者 Object 类的 wait(long timeout) 方法,进入计时等待状态。这个状态适用于希望线程暂停一段时间后再继续执行的场景。

这些状态的灵活转换和合理运用,可以实现线程之间的协作、资源的共享和利用,提高程序的并发性能和响应速度。但需要注意的是,对于多线程编程,需要注意线程安全和同步的问题,避免产生不确定的结果和竞态条件。


五、JAVA五态面试题

  1. 请解释Java中线程的五种状态是什么?
  2. 在 Java 中,如何将一个线程从新建状态转变为运行状态?
  3. 什么情况下会使一个线程从运行状态转变为阻塞状态?
  4. 什么是等待状态和计时等待状态?它们之间有何区别?
  5. 如何将一个线程从运行状态转变为等待状态或计时等待状态?
  6. 如何将一个线程从等待状态或计时等待状态转变为运行状态?
  7. 什么情况下会使一个线程从运行状态转变为终止状态?
  8. 在 Java 中,如何正确处理线程的状态转换,以避免潜在的并发问题?


六、总结

本文讲解了 Java 中 三态和五态的概念,介绍了新建、运行、状态、阻塞、等待、计时等待状态的应用场景,并给出了样例代码,在下一篇博客中,将讲解 Java 如何实现线程的创建和启动。


相关文章
|
1月前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
1月前
|
安全 Java 调度
【Java】JavaSE实现多线程
【Java】JavaSE实现多线程
66 1
|
1月前
|
消息中间件 Linux 调度
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
127 0
|
20天前
|
设计模式 安全 Java
Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)
Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)
|
24天前
|
Java API 调度
JavaSE基础精选-多线程
JavaSE基础精选-多线程
23 0
|
27天前
|
存储 网络协议 iOS开发
connect永远阻塞线程及解决方案
connect永远阻塞线程及解决方案
19 0
|
1月前
|
Java API 分布式数据库
实时计算 Flink版产品使用合集之如何解决 TaskManager和 JobManager中有大量的等待线程
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
1月前
|
前端开发 JavaScript UED
由于JavaScript是单线程的,因此在处理大量异步操作时,需要确保不会阻塞UI线程
【5月更文挑战第13天】JavaScript中的Promise和async/await常用于处理游戏开发中的异步操作,如加载资源、网络请求和动画帧更新。Promise表示异步操作的结果,通过.then()和.catch()处理回调。async/await作为Promise的语法糖,使异步代码更简洁,类似同步代码。在游戏循环中,使用async/await可清晰管理资源加载和更新,但需注意避免阻塞UI线程,并妥善处理加载顺序、错误和资源管理,以保证游戏性能和稳定性。
31 3
|
1月前
简便的方法开线程干活并且出现等待提示
简便的方法开线程干活并且出现等待提示
18 3
|
1月前
|
安全 算法 关系型数据库
线程安全--深入探究线程等待机制和死锁问题
线程安全--深入探究线程等待机制和死锁问题

热门文章

最新文章

相关实验场景

更多