线程的生命周期与常用方法
线程是操作系统能够进行运算调度的最小单位。
它被包含在进程之中,是进程中的实际运作单位。
线程的生命周期描述了线程从创建到终止的过程,而常用方法则提供了控制和交互线程的手段。
线程的生命周期
线程的生命周期包括以下几个状态:
- 新建状态(New):线程对象被创建,但还没有调用start()方法,因此线程还没有开始执行。
- 就绪状态(Runnable):当调用线程的start()方法后,线程就进入就绪状态。在这个状态下,线程只是进入了线程队列,等待CPU的调度,并不代表线程立即就能执行。
- 运行状态(Running):线程获得CPU时间片后,它就开始执行run()方法中的代码,进入运行状态。
- 阻塞状态(Blocked):线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况包括:等待I/O操作的完成、等待获取一个锁、等待从Thread.sleep()方法返回等。
- 死亡状态(Dead):线程执行完run()方法后,或者因为异常退出了run()方法,该线程结束生命周期。
线程的常用方法
线程的常用方法包括:
- start():使该线程开始执行;Java虚拟机调用该线程的run()方法。
- run():如果该线程是使用独立的Runnable运行对象构造的,则调用该Runnable对象的run()方法;否则,该方法不执行任何操作并返回。
- currentThread():返回对当前正在执行的线程对象的引用。
- isAlive():测试线程是否处于活动状态。
- sleep(long millis):在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
- join():等待该线程终止。
- yield():暂停当前正在执行的线程对象,并执行其他线程。
- interrupt():中断线程。如果线程在调用Object类的wait()、wait(long)或wait(long, int)方法,或者该类的join()、join(long)、join(long, int)、sleep(long)或sleep(long, int)方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException。
这些方法提供了创建、启动、控制和终止线程的能力,是Java多线程编程的基础。为了更直观地讲解线程的生命周期与常用方法,我将通过示例来说明。
线程的生命周期示例
假设我们有一个简单的Java程序,它创建并启动了一个线程。这个线程的生命周期可以大致分为以下几个阶段:
public class ThreadLifecycleExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
// 模拟线程执行任务
Thread.sleep(1000); // 线程可能处于TIMED_WAITING状态
System.out.println("Thread is running...");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 线程处于 NEW 状态
System.out.println("Thread state after creation: " + thread.getState()); // 输出 NEW
// 启动线程,线程进入 RUNNABLE 状态
thread.start();
System.out.println("Thread state after calling .start(): " + thread.getState()); // 输出 RUNNABLE,注意此时线程可能还未真正运行
// 等待线程结束
try {
thread.join(); // 主线程等待子线程结束
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 线程执行完毕,进入 TERMINATED 状态
System.out.println("Thread state after completion: " + thread.getState()); // 输出 TERMINATED
}
}
在这个示例中,线程的生命周期经历了以下阶段:
- 新建状态(NEW):线程对象被创建,但尚未启动。
- 可运行状态(RUNNABLE):调用线程的start()方法后,线程进入可运行状态,等待CPU调度执行。注意,RUNNABLE状态包括了传统意义上的就绪和运行两种状态。
- 运行状态(实际上在RUNNABLE状态内):线程获得CPU时间片后执行run()方法中的代码。
- 可能进入的阻塞或等待状态:在这个例子中,线程通过调用sleep()方法进入了TIMED_WAITING状态,这是阻塞状态的一种。在实际应用中,线程还可能因为其他原因(如等待I/O操作、等待锁等)进入阻塞或等待状态。
- 终止状态(TERMINATED):线程执行完run()方法中的代码后,进入终止状态。
线程的常用方法示例
线程的常用方法包括start()、run()、sleep()、join()等,它们在上述示例中已有体现。以下是这些方法的简要说明和示例:
-
start():启动线程,使线程从新建状态进入可运行状态。
示例:
thread.start();
-
run():线程启动后,JVM会调用线程的run()方法来执行线程的任务。
注意:用户不应该直接调用线程的run()方法,而应该通过调用start()方法来启动线程。
-
sleep(long millis):使当前线程暂停执行指定的毫秒数,进入TIMED_WAITING状态。
示例:
Thread.sleep(1000);
-
join():等待当前线程终止。调用某个线程的join()方法会使当前线程阻塞,直到该线程终止。
示例:
thread.join();
-
yield():提示调度器当前线程愿意放弃当前的CPU时间片,让其他线程运行。但调度器可以忽略这个提示。
示例:
Thread.yield();
-
interrupt():中断线程。调用线程的interrupt()方法会设置该线程的中断状态为true,但不会立即停止线程的执行。线程需要定期检查自己的中断状态,并根据需要做出响应。
示例:虽然示例中没有直接使用interrupt(),但在处理InterruptedException时通常会调用Thread.currentThread().interrupt()来保持中断状态。
通过理解线程的生命周期和常用方法,我们可以更好地编写和管理多线程程序,提高程序的并发性能和稳定性。
欢迎访问我的公众号或博客(点击查看头像信息)