Java教程-线程的生命周期(线程状态)

线程的生命周期(线程状态)
在Java中,一个线程总是存在于以下状态之一。这些状态包括:
- 新建状态(New)
- 活动状态(Active)
- 阻塞/等待状态(Blocked / Waiting)
- 有时限的等待状态(Timed Waiting)
- 终止状态(Terminated)
不同线程状态的解释
新建状态(New):当创建一个新线程时,它始终处于新建状态。对于新建状态的线程,代码尚未运行,因此还未开始执行。
活动状态(Active):当一个线程调用start()方法时,它从新建状态转移到活动状态。活动状态包含两个子状态:一个是可运行(Runnable)状态,另一个是运行(Running)状态。
- 可运行(Runnable):一个准备运行的线程会被移动到可运行状态。在可运行状态中,线程可以正在运行,也可能在任何给定的时刻准备运行。线程调度器的职责是为线程提供运行的时间,即将线程移动到运行状态。实现多线程的程序将为每个线程获得固定的时间片。每个线程运行一小段时间,当分配的时间片用完时,线程自愿放弃CPU,以便其他线程也能运行它们的时间片。当发生这种情况时,所有愿意运行、等待轮到它们运行的线程都处于可运行状态。在可运行状态中,有一个线程队列。
- 运行(Running):当线程获得CPU时,它从可运行状态转移到运行状态。通常,线程状态的最常见变化是从可运行到运行,再从运行返回可运行。
阻塞/等待状态(Blocked / Waiting):当线程在一段时间内处于非活动状态(非永久性)时,它要么处于阻塞状态,要么处于等待状态。
例如,一个线程(假设其名称为A)可能希望从打印机中打印一些数据。然而,同时,另一个线程(假设其名称为B)正在使用打印机打印一些数据。因此,线程A必须等待线程B使用打印机。因此,线程A处于阻塞状态。阻塞状态的线程无法执行任何操作,因此不会消耗中央处理单元(CPU)的任何周期。因此,我们可以说线程A保持空闲状态,直到线程调度器重新激活处于等待或阻塞状态的线程A。
当主线程调用join()方法时,主线程处于等待状态。主线程等待子线程完成其任务。当子线程完成工作时,会发送通知给主线程,主线程再次将线程从等待状态转移到活动状态。
如果有很多线程处于等待或阻塞状态,则线程调度器负责确定选择哪个线程和拒绝哪个线程,选择的线程将获得运行的机会。
有时限的等待状态(Timed Waiting):有时,等待会导致饥饿。例如,一个线程(名称为A)进入了代码的临界区并且不愿意离开该临界区。在这种情况下,另一个线程(名称为B)必须永远等待,导致饥饿现象。为了避免这种情况,线程B被赋予一个有时限的等待状态。因此,线程在等待状态下等待一段特定的时间,而不是永远等待。有时限等待的一个真实例子是在特定线程上调用sleep()方法。sleep()方法将线程置于有时限的等待状态。时间到期后,线程唤醒并从之前离开的地方开始执行。
终止状态(Terminated):线程达到终止状态有以下原因:
- 当一个线程完成其工作时,它正常退出或终止。
- 异常终止:发生异常事件(如未处理的异常或分段错误)时发生。
终止的线程意味着线程不再存在于系统中。换句话说,线程已经结束,无法重新启动(杀死后再次活动)已经结束的线程。
下图展示了线程生命周期中涉及的不同状态。
线程状态的实现
在Java中,可以使用Thread.getState()方法获取线程的当前状态。Java的java.lang.Thread.State类提供了枚举常量来表示线程的状态。这些常量包括:
public static final Thread.State NEW
它表示线程的第一个状态,即NEW状态。
public static final Thread.State RUNNABLE
它表示可运行状态。这意味着线程正在等待在队列中运行。
public static final Thread.State BLOCKED
它表示阻塞状态。在该状态下,线程正在等待获取锁。
public static final Thread.State WAITING
它表示等待状态。当线程调用Object.wait()方法或Thread.join()方法而没有超时时,线程将进入此状态。处于等待状态的线程正在等待另一个线程完成其任务。
public static final Thread.State TIMED_WAITING
它表示有时限的等待状态。等待状态和有时限等待状态的主要区别在于时间限制。等待状态没有时间限制,而有时限等待状态有时间限制。调用以下方法的线程将进入有时限等待状态:
- sleep
- join with timeout
- wait with timeout
- parkUntil
- parkNanos
public static final Thread.State TERMINATED
它表示线程的最终状态,即终止或已结束。终止的线程表示其已完成执行。
用于演示线程状态的Java程序
以下是一个展示上述线程状态的Java程序。
文件名:ThreadState.java
// ABC类实现接口Runnable
class ABC implements Runnable
{
public void run()
{
// try-catch 块
try
{
// 将线程 t2 转移到定时等待状态
Thread.sleep(100);
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("The state of thread t1 while it invoked the method join() on thread t2 -"+ ThreadState.t1.getState());
// try-catch 块
try
{
Thread.sleep(200);
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
}
}
// ThreadState类实现接口Runnable
public class ThreadState implements Runnable
{
public static Thread t1;
public static ThreadState obj;
// 主要方法
public static void main(String argvs[])
{
// 创建类 ThreadState 的对象
obj = new ThreadState();
t1 = new Thread(obj);
// 线程 t1 被生成
// 线程 t1 当前处于 NEW 状态。
System.out.println("The state of thread t1 after spawning it - " + t1.getState());
// 调用 start() 方法
// 线程t1
t1.start();
// 线程 t1 进入 Runnable 状态
System.out.println("The state of thread t1 after invoking the method start() on it - " + t1.getState());
}
public void run()
{
ABC myObj = new ABC();
Thread t2 = new Thread(myObj);
// 线程 t2 已创建并且当前处于 NEW 状态。
System.out.println("The state of thread t2 after spawning it - "+ t2.getState());
t2.start();
// 线程 t2 进入可运行状态
System.out.println("the state of thread t2 after calling the method start() on it - " + t2.getState());
// try-catch 块用于程序的流畅运行
try
{
// 将线程 t1 转移到定时等待状态
Thread.sleep(200);
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("The state of thread t2 after invoking the method sleep() on it - "+ t2.getState() );
// try-catch 块用于程序的流畅运行
try
{
// 等待线程 t2 完成执行
t2.join();
}
catch (InterruptedException ie)
{
ie.printStackTrace();
}
System.out.println("The state of thread t2 when it has completed it's execution - " + t2.getState());
}
}
输出:
The state of thread t1 after spawning it - NEW
The state of thread t1 after invoking the method start() on it - RUNNABLE
The state of thread t2 after spawning it - NEW
the state of thread t2 after calling the method start() on it - RUNNABLE
The state of thread t1 while it invoked the method join() on thread t2 -TIMED_WAITING
The state of thread t2 after invoking the method sleep() on it - TIMED_WAITING
The state of thread t2 when it has completed it's execution - TERMINATED
解释:当我们创建一个新线程时,该线程处于NEW状态。当在线程上调用start()方法时,线程调度器将该线程移动到RUNNABLE状态。当在任何线程实例上调用join()方法时,执行该语句的当前线程必须等待该线程完成执行,即将该线程移动到TERMINATED状态。因此,在最终的打印语句被打印到控制台之前,程序在线程t2上调用join()方法,使线程t1等待,直到线程t2完成执行,因此线程t2进入终止状态。线程t1进入等待状态,因为它正在等待线程t2完成执行,而线程t1在线程t2上调用了join()方法。