基于 Java 线程的几种状态(详解)
在 Java 语言中,线程是一种非常重要的概念。线程可以被分为多个状态,在不同的状态下,线程的行为和特征是不同的。本文将详细介绍基于 Java 线程的几种状态,并通过两个示例来演示它们。
线程的状态
在 Java 中,线程有以下几种状态:
- 新建状态(New):线程尚未启动,处于新建状态。
- 运行状态(Running):线程正在执行运行代码。
- 阻塞状态(Blocked):线程被阻塞了,等待某个条件的到来,例如等待 I/O 完成,或等待某个锁的释放。
- 等待状态(Waiting):线程在等待某个条件的唤醒,例如等待用户输入,或等待某个状态的改变。
- 计时等待状态(Timed Waiting):线程正在等待某个条件的唤醒,但是在等待的过程中,可以设置一个超时时间,如果超时还没有被唤醒,线程也会自行唤醒。
- 终止状态(Terminated):线程已经执行完毕,进入终止状态。
示例一
下面的代码演示了多个线程在不同状态下的行为。
public class ThreadStatesDemo {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// 进入运行状态
System.out.println("Thread 1 is running...");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (ThreadStatesDemo.class) {
// 进入阻塞状态
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 进入等待状态
System.out.println("Thread 3 is waiting for user input...");
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 进入计时等待状态
System.out.println("Thread 4 is waiting for 5 seconds...");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 启动所有线程
t1.start();
t2.start();
t3.start();
t4.start();
// 等待所有线程执行完毕
t1.join();
t2.join();
t3.join();
t4.join();
// 所有线程执行完毕
System.out.println("All threads have terminated.");
}
}
在上面的示例代码中,我们启动了四个线程,分别进入不同的状态。具体来说:
- 线程
t1
进入了运行状态,因为它没有任何被阻塞的代码。 - 线程
t2
进入了阻塞状态,因为它在一个 synchronized 块中等待着另一个线程释放同步锁。 - 线程
t3
进入了等待状态,因为它在等待用户输入。 - 线程
t4
进入了计时等待状态,因为它在等待 5 秒钟之后会自动唤醒。
示例二
我们可以用一个稍微复杂一些的例子来说明线程状态的变化。
public class ThreadStatesDemo2 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (ThreadStatesDemo2.class) {
System.out.println("Thread 1 has acquired the lock, will sleep for 5 seconds");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (ThreadStatesDemo2.class) {
System.out.println("Thread 2 has acquired the lock");
}
}
});
// 启动线程 t1,它会拿到锁并且休眠 5 秒钟,t2 获取锁之后等待 10 秒钟
t1.start();
Thread.sleep(500);
t2.start();
Thread.sleep(10000);
// t1 已经醒来并且释放了锁,t2 继续往下执行
System.out.println("Thread 2 is still running after 10 seconds");
Thread.sleep(5000);
// 等待线程执行完毕并退出
t1.join();
t2.join();
}
}
在这个例子中,我们启动了两个线程 t1
和 t2
。t1
进入了阻塞状态,等待 5 秒钟之后醒来并且释放锁。t2
在启动之后,需要等待 5 秒钟才能获取锁并且继续往下执行。在这个过程中,t1
和 t2
的状态都发生了变化,具体如下:
- 线程
t1
进入了阻塞状态,因为它在一个 synchronized 块中等待着另一个线程释放同步锁。 - 线程
t2
进入了阻塞状态,因为它在一个 synchronized 块中等待着另一个线程释放同步锁。 - 线程
t1
进入了计时等待状态,因为它在等待 5 秒钟之后会自动唤醒。 - 线程
t2
进入了等待状态,因为它在等待另一个线程释放锁。 - 线程
t2
进入了计时等待状态,因为它在等待 5 秒钟之后会自动唤醒。
结论
在 Java 中,线程有多种状态,每种状态都有其特点和行为。正确理解线程的状态可以帮助程序员编写出更加高效的多线程程序。在官方文档和其他实践指南中,作者提供了更多的线程状态改变的示例和详细解释。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于java 线程的几种状态(详解) - Python技术站