一、java线程的6种状态
Java线程在其生命周期中会经历不同的状态,Java语言在Thread.State枚举中明确定义了6种线程状态:
1、NEW(新建状态)
2、RUNNABLE(可运行状态)
3、TIMED_WAITING(计时等待状态)
4、BLOCKED(阻塞状态)
5、WAITING(等待状态)
6、TERMINATED(终止状态)
二、各状态详解及转换条件
1、NEW(新建状态)
含义:线程被创建但尚未启动时的状态。此时线程对象已存在,但还没有调用start()方法。
Thread t=new Thread();
System.out.println(t.getState());
2、RUNNABLE(可运行状态)
含义:可工作的,又分为正在工作和随时准备工作
NEW → RUNNABLE转换条件:调用线程的start()方法
Thread t=new Thread();//此时线程处于NEW状态
t.start();//转换为RUNNABLE状态
System.out.println(t.getState());
3、TIMED_WAITING(限时等待状态)
含义:线程在指定时间内等待,超时后自动返回,无需显示唤醒。
RUNNABLE→ TIMED_WAITING进入方式:
(1)Thread.sleep(long)
(2)Object.wait(long)
(3)Thread.join(long)
(4)LockSupport.parkNanos()
(5)LockSupport.parkUntil()
TIMED_WAITING→ RUNNABLE:等待时间结束或被唤醒
举个例子:
Thread t=new Thread(()->{
try{
System.out.println("线程状态: " + Thread.currentThread().getState()); // RUNNABLE
Thread.sleep(2000); // 进入TIMED_WAITING
System.out.println("当前状态: " + Thread.currentThread().getState()); // RUNNABLE
}catch(InterruptedException e){
e.printStackTrace();
}
});
t.start();
while(t.getState() != Thread.State.TERMINATED){
Thread.sleep(1000);
System.out.println("当前状态: " + t.getState());
}
代码运行结果如下:
从这个结果我们可以看出带有时间参数的sleep方法可以让线程进入 TIMED_WAITING状态,同样的join(时间)等方法也能进入TIMED_WAITING状态
4、 BLOCKED(阻塞状态)
含义:线程因为等待获取一个排它锁而被阻塞的状态。(通俗来说,就是t1线程持有锁,t2线程现在要尝试获取这个锁,如果无法获取就进入BLOCKED状态)
RUNNABLE→BLOCKED进入方式:
等待进入synchronized方法/块
synchronized(lock) { // 如果其他线程持有lock,当前线程会进入BLOCKED状态
// 获取到锁后进入RUNNABLE状态
}
BLOCKED → RUNNABLE:成功获取到所需的锁
特点:
必须有两个以上线程竞争同一把锁才会出现
不消耗CPU资源
不可中断
接下来我们来看一段完整的代码理解这个阻塞过程
private static final Object lock = new Object(); // 共享锁对象
public static void main(String[] args) throws InterruptedException {
// 线程1 - 持有锁3秒
Thread t1 = new Thread(() -> {
synchronized (lock) {
System.out.println("线程1获取锁,状态: " + Thread.currentThread().getState());
try {
Thread.sleep(3000); // TIMED_WAITING
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 线程2 - 尝试获取锁
Thread t2 = new Thread(() -> {
System.out.println("线程2尝试获取锁...");
synchronized (lock) { // 这里会BLOCKED
System.out.println("线程2获取锁成功");
}
});
t1.start();
Thread.sleep(100); // 确保t1先获取锁
t2.start();
// 监控t2状态
while(true) {
System.out.println("线程2状态: " + t2.getState());
if(t2.getState() == Thread.State.TERMINATED) break;
Thread.sleep(500);
}
}
代码运行结果如下:
我们将 BLOCKED与TIMED_WAITING进行比对
TIMED_WAITING:由sleep()、wait(timeout)等方法引起,是主动等待
BLOCKED:由锁竞争引起,是被动阻塞
5、WAITING(无限期等待状态)
含义:线程无限期等待其他线程执行特定操作,需要被显式唤醒。
RUNNABLE→ TIMED_WAITING进入方式:
调用
Object.wait()
调用
Thread.join()
调用
LockSupport.park()
synchronized(lock) {
lock.wait(); // 进入WAITING状态
}
WAITING → RUNNABLE:被其他线程唤醒(notify()/notifyAll()或目标线程终止)
synchronized(lock) {
lock.notify(); // 唤醒等待线程
}
我们来看一段完整的过程
private static final Object lock = new Object(); // 共享锁对象
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
synchronized (lock){
try {
System.out.println("线程状态: " + Thread.currentThread().getState()); // RUNNABLE
lock.wait(); // 释放锁并进入WAITING状态
System.out.println("当前状态: " + Thread.currentThread().getState()); // RUNNABLE
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
//状态监控循环
while(true){
System.out.println("当前状态:"+t.getState());
if(t.getState() == Thread.State.WAITING){
synchronized (lock) {//获取同一把锁
System.out.println("[主线程] 检测到WAITING状态,准备唤醒...");
lock.notify();//唤醒等待线程
System.out.println("[主线程] 已发送唤醒通知");
}
}
if (t.getState() == Thread.State.TERMINATED) {
break;//终止线程循环
}
Thread.sleep(300); // 监控间隔
}
}
代码的运行结果如下:
6、TERMINATED(终止状态)
含义:线程执行完毕(run()方法正常结束)或因异常退出后的状态。
进入TERMINATED状态
(1)、正常完成执行
new Thread(() -> {
System.out.println("执行任务...");
// run()方法自然结束
}).start();
(1)、抛出未捕获的异常
new Thread(() -> {
throw new RuntimeException("意外错误");
}).start();
注意:
一旦进入TERMINATED状态,线程就不能再次启动,具有不可逆性;
线程栈等资源会被JVM回收,但Thread对象本身仍然存在;
可通过getState()方法检测,isAlive()方法返回false
TERMINATED状态与其他状态的关系
NEW → RUNNABLE → (BLOCKED/WAITING/TIMED_WAITING) → RUNNABLE → TERMINATED
下面我们来看一段完整的过程:
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
System.out.println("线程开始执行...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
// 监控线程状态变化
while (t.getState() != Thread.State.TERMINATED) {
System.out.println("运行中状态: " + t.getState());
Thread.sleep(300);
}
System.out.println("最终状态: " + t.getState()); // TERMINATED
// 尝试重新启动
try {
t.start(); // 抛出IllegalThreadStateException
} catch (IllegalThreadStateException e) {
System.out.println("不能重新启动已终止的线程");
}
}
代码运行结果如下:
三、总结
状态变化简易图
实例化
│
▼
NEW (新建)
│
│ Thread.start()
▼
┌─────────────┐
│ RUNNABLE │◄──────────────────────┐
│ (可运行) │ │
├─────┬───────┤ │
│READY│RUNNING│ │
└─────┴───────┘ │
│ │ │
│ │ 竞争锁失败 │
│ ▼ │
│ BLOCKED (阻塞) │
│ │ │
│ │ 获取到锁 │
│ ▼ │
│ wait()/join()/park() notify()/unpark()
▼ │ │
WAITING (无限等待) │
│ │ │
│ │ sleep(timeout)/wait(timeout)│
▼ ▼ │
TIMED_WAITING (超时等待) │
│ │ │
│ │ 超时/被唤醒 │
└────┴────────────────────────────┘
│
│ 执行完成
▼
TERMINATED (终止)