线程状态
6种状态
从源码出发,java.lang.Thread 定义了一个内部枚举 java.lang.Thread.State ,该枚举用于罗列 JAVA 线程的所有状态,分别是NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
- NEW:新建状态,实例化后处于该状态( new Thread() ) 。
- RUNNABLE:可执行状态,调用 start() 之后处于该状态 ,包括准备( Ready )和执行 ( Running )。
- BLOCKED: 阻塞状态,在竞争锁失败后进入该状态。
- WAITING: 等待状态,由于调用了Object.wait()、Thread.join()、LockSupport.park()其中一个方法,线程进入等待状态态。
- TIMED_WAITING: 有指定等待时间的线程等待状态,LockSupport.parkNanos(long)、LockSupport.parkUntil(long)其中一个方法并传入了正(数)时间参数。
- TERMINATED: 终止状态,线程已经执行完成。
其中需要注意的是:RUNNABLE 包括了 准备( Ready )和执行 ( Running ),实际上,调用 start() API 之后线程并非立马执行(准备),需要等待 CPU 调度才执行该线程的业务逻辑(执行)。
状态转换图
常规情况下,大多数线程基本都是经历 NEW --> RUNNABLE --> TERMINATED 的生命历程,此外线程在 RUNNABLE 也可以进入 BLOCKED、WAITING、TIMED_WAITING状态。
状态使用
NEW
实例化 Thread 后进入该状态。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
public void run() {
System.out.println("hello world");
}
});
System.out.println("线程状态为:" + thread.getState());
}
}
输出结果:
线程状态为:NEW
RUNNABLE
调用 start() 方法后进入该状态。
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
public void run() {
System.out.println("执行run方法,线程状态为:" + Thread.currentThread().getState());
System.out.println("hello world");
}
});
System.out.println("线程状态为:" + thread.getState());
thread.start();
}
}
输出结果:
线程状态为:NEW
执行run方法,线程状态为:RUNNABLE
hello world
TERMINATED
线程争取到 CPU 执行时间片,执行完所有的业务逻辑,自动进入该状态。
public class TestThread {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
public void run() {
System.out.println("执行run方法,线程状态为:" + Thread.currentThread().getState());
System.out.println("hello world");
}
});
System.out.println("线程状态为:" + thread.getState());
thread.start();
Thread.sleep(1000);
System.out.println("线程状态为:" + thread.getState());
}
}
输出结果:
线程状态为:NEW
执行run方法,线程状态为:RUNNABLE
hello world
线程状态为:TERMINATED
BLOCKED
多个线程竞争同一把锁,如果竞争锁失败,进入该状态。
public class TestThread {
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
System.out.println("执行run方法,线程状态为:" + Thread.currentThread().getState());
}
}
});
System.out.println("线程状态为:" + thread.getState());
synchronized (lock) {
// 启动 thread 线程,但是 main 线程先获取到锁
thread.start();
// 模拟长时间占用锁,
Thread.sleep(1000);
System.out.println("线程状态为:" + thread.getState());
}
Thread.sleep(1000);
System.out.println("线程状态为:" + thread.getState());
}
}
输出结果:
线程状态为:NEW
线程状态为:BLOCKED
执行run方法,线程状态为:RUNNABLE
线程状态为:TERMINATED
WAITING
当线程不满足执行条件时,选择让线程进入等待状态,在条件满足之后唤醒。通常用于解决条件不足但是线程竞争资源致使关键线程无法执行的情况 关于更多WAITING的介绍推荐查看此处。
public class ATM {
private int money;
Object object = new Object();
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void add(int money) {
synchronized (object) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.money += money;
System.out.println(Thread.currentThread().getName() + "存入money:" + money);
System.out.println("当前money:" + this.money);
// 有钱了,唤醒所有在等待set中的线程去取钱
object.notifyAll();
}
}
public void del(int money) {
synchronized (object) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (this.money <= 0) {
try {
System.out.println("没有money了进入等待");
// 没有钱了,再争抢锁也没有用,先把锁释放掉,开始等待,让存钱线程获取到锁,进行存钱操作
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
this.money -= money;
System.out.println(Thread.currentThread().getName() + "取走money:" + money);
System.out.println("当前money:" + this.money);
}
}
}
}
public class TestThread {
static ATM atm = new ATM();
public static void main(String[] args) throws InterruptedException {
atm.setMoney(10000);
Thread[] bankVipthreads = new Thread[2];
// 模拟两个VIP会员往ATM机取钱
for (int i = 0; i < bankVipthreads.length; i++) {
bankVipthreads[i] = new Thread(new Runnable() {
public void run() {
while(true) {
atm.del(5000);
}
}
}, "银行VIP会员取钱线程" + i);
}
// 模拟一个个银行职员往ATM机存钱
Thread bankClerk = new Thread(new Runnable() {
public void run() {
while(true) {
atm.add(10000);
}
}
}, "银行职员存钱线程");
bankVipthreads[0].start();
bankVipthreads[1].start();
// 确保VIP会员先取钱
Thread.sleep(3000);
bankClerk.start();
}
}
输出结果:
银行VIP会员取钱线程0取走money:5000
当前money:5000
银行VIP会员取钱线程0取走money:5000
当前money:0
没有money了进入等待
没有money了进入等待
银行职员存钱线程存入money:10000
当前money:10000
银行职员存钱线程存入money:10000
当前money:20000
银行职员存钱线程存入money:10000
当前money:30000
银行职员存钱线程存入money:10000
当前money:40000
银行职员存钱线程存入money:10000
当前money:50000
银行职员存钱线程存入money:10000
当前money:60000
银行职员存钱线程存入money:10000
当前money:70000
银行职员存钱线程存入money:10000
当前money:80000
银行职员存钱线程存入money:10000
当前money:90000
银行职员存钱线程存入money:10000
当前money:100000
银行职员存钱线程存入money:10000
当前money:110000
银行VIP会员取钱线程1取走money:5000
当前money:105000
银行VIP会员取钱线程1取走money:5000
当前money:100000
银行VIP会员取钱线程1取走money:5000
当前money:95000
银行VIP会员取钱线程1取走money:5000
当前money:90000
银行VIP会员取钱线程1取走money:5000
当前money:85000
银行VIP会员取钱线程1取走money:5000
当前money:80000
银行VIP会员取钱线程0取走money:5000
当前money:75000
银行VIP会员取钱线程0取走money:5000
当前money:70000
银行VIP会员取钱线程0取走money:5000
当前money:65000
银行VIP会员取钱线程0取走money:5000
当前money:60000
银行VIP会员取钱线程0取走money:5000
当前money:55000
银行VIP会员取钱线程0取走money:5000
当前money:50000
银行VIP会员取钱线程0取走money:5000
当前money:45000
银行VIP会员取钱线程0取走money:5000
当前money:40000
银行VIP会员取钱线程0取走money:5000
当前money:35000
银行VIP会员取钱线程0取走money:5000
当前money:30000
银行VIP会员取钱线程0取走money:5000
当前money:25000
银行VIP会员取钱线程0取走money:5000
当前money:20000
银行VIP会员取钱线程0取走money:5000
当前money:15000
银行VIP会员取钱线程0取走money:5000
当前money:10000
银行VIP会员取钱线程0取走money:5000
当前money:5000
银行VIP会员取钱线程0取走money:5000
当前money:0
没有money了进入等待
银行职员存钱线程存入money:10000
当前money:10000
银行职员存钱线程存入money:10000
当前money:20000
银行职员存钱线程存入money:10000
当前money:30000
TIMED_WAITING
线程进入指定时间等待 。超时自动唤醒进入到 Runable 状态准备执行。和 WAITING 相比,该状态是超时自动唤醒。
package base;
public class TestThread {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
public void run() {
synchronized (lock) {
try {
// thread 进入有时间限制的等待状态
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行run方法,线程状态为:" + Thread.currentThread().getState());
}
}
});
System.out.println("线程状态为:" + thread.getState());
// 启动 thread 线程,
thread.start();
// main 进入有时间限制的等待状态,把 cpu 让给 thread
Thread.sleep(200);
System.out.println("线程状态为:" + thread.getState());
Thread.sleep(2000);
System.out.println("线程状态为:" + thread.getState());
}
}
输出结果:
线程状态为:NEW
线程状态为:TIMED_WAITING
执行run方法,线程状态为:RUNNABLE
线程状态为:TERMINATED