1.一图胜千言
我们通过一幅图,展示线程生命周期中各种状态的转换。
2.状态转换案例
2.1.状态:NEW/RUNNABLE/TERMINATED
通过该案例,演示线程的NEW/RUNNABLE/TERMINATED状态。
package com.anan.thread.threadstate;
import java.util.concurrent.TimeUnit;
/**
* 演示线程状态:NEW/RUNNABLE/TERMINATED
*/
public class ThreadStateDemo1 {
public static void main(String[] args) throws InterruptedException{
// 创建线程对象
String tName = "my-thread";
Runnable r1 = new MyRunnable();
Thread t1 = new Thread(r1,tName);
// 输出线程状态:NEW
System.out.println("1.新建线程:" + tName + "当前状态:" + t1.getState());
// 启动线程,等待1毫秒,输出线程状态:RUNNABLE
t1.start();
TimeUnit.MILLISECONDS.sleep(1);
System.out.println("2.启动线程后:" + tName + "当前状态:" + t1.getState());
// 发送中断信号,等待1毫秒,输出线程状态:TERMINATED
t1.interrupt();
TimeUnit.MILLISECONDS.sleep(1);
System.out.println("3.给线程发送中断信号后:" + tName + "当前状态:" + t1.getState());
}
}
/**
* 实现Runnable接口,创建线程
*/
class MyRunnable implements Runnable{
public void run() {
while (!Thread.currentThread().isInterrupted()){
;// 不断循环,等待中断信号发生,然后结束线程运行
}
System.out.println("中断信号发生," + Thread.currentThread().getName() + "准备结束运行.");
}
}
2.2.状态:BLOCKED
通过该案例,演示线程的BLOCKED状态。业务描述:
1.模拟获取共享资源银行:Bank账户余额信息,在获取账户余额时,需要加上同步锁
2.创建两个线程,并发获取银行账户余额,模拟当一个线程加锁操作中,另外一个线程只能阻塞等待
3.在主线程中,输出两个线程的状态
package com.anan.thread.threadstate;
import java.util.concurrent.TimeUnit;
/**
* 演示线程状态:BLOCKED
*/
public class ThreadStateBlockedDemo {
// 公共锁对象
public static final Object LOCK = new Object();
/**
* 2.创建两个线程,并发获取银行账户余额,
* 模拟当一个线程加锁操作中,另外一个线程只能阻塞等待
*/
public static void main(String[] args) {
// 创建Runnable对象
Runnable r1 = new MyRunnable1();
// 创建两个线程对象
String tName_1 = "my-thread-1";
Thread t1 = new Thread(r1,tName_1);
String tName_2 = "my-thread-2";
Thread t2 = new Thread(r1,tName_2);
// 启动线程t1,t2
t1.start();
t2.start();
// 输出两个线程:t1,t2当前状态
System.out.println("1.主线程"+ Thread.currentThread().getName() +
"打印,线程:" + t1.getName() + "当前状态:" + t1.getState());
System.out.println("2.主线程"+ Thread.currentThread().getName() +
"打印,线程:" + t2.getName() + "当前状态:" + t2.getState());
}
/**
* 1.模拟获取共享资源银行:Bank
* 账户余额信息,在获取账户余额时,需要加上同步锁
*/
public static void getBankMoney() {
synchronized (LOCK){
System.out.println(Thread.currentThread().getName() + "线程,获取到锁###.");
// 休眠1秒,模拟业务操作
try {
TimeUnit.SECONDS.sleep(1);
// 打印输出账户余额
System.out.println("线程:" + Thread.currentThread().getName() +
"获取到账户余额了......");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "线程,释放锁###.");
}
}
/**
* 实现Runnable接口,创建线程
*/
class MyRunnable1 implements Runnable{
public void run() {
// 获取账户余额
ThreadStateBlockedDemo.getBankMoney();
}
}
2.3.状态:WAITING
通过该案例,演示线程的WAITING状态。
package com.anan.thread.threadstate;
import java.util.concurrent.TimeUnit;
/**
* 演示线程状态:WAITING
*/
public class ThreadStateWaitingDemo {
// 创建公共锁
public final static Object LOCK = new Object();
public static void main(String[] args) throws InterruptedException{
// 创建线程对象
Runnable r1 = new MyRunnable3();
String tName_1 = "my-thread-1";
Thread t1 = new Thread(r1,tName_1);
// 启动线程,休眠1秒后,获取线程状态
t1.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("1.主线程"+ Thread.currentThread().getName() +
"打印,线程:" + t1.getName() + "当前状态:" + t1.getState());
// 主线程唤醒t1线程,再次输出线程状态
synchronized (LOCK){
LOCK.notify();
}
TimeUnit.SECONDS.sleep(1);
System.out.println("2.主线程"+ Thread.currentThread().getName() +
"打印,线程:" + t1.getName() + "当前状态:" + t1.getState());
}
}
/**
* 实现Runnable接口,创建线程
*/
class MyRunnable3 implements Runnable{
public void run() {
System.out.println("线程:" + Thread.currentThread().getName() +
"即将进入等待:ThreadStateWaitingDemo.LOCK.wait(),等待主线程输出状态.");
synchronized (ThreadStateWaitingDemo.LOCK){
try {
ThreadStateWaitingDemo.LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程:" + Thread.currentThread().getName() +
"被唤醒执行结束,等待主线程输出状态.");
}
}
2.4.状态:TIMED_WAITING
通过该案例,演示线程的TIMED_WAITING状态。
package com.anan.thread.threadstate;
import java.util.concurrent.TimeUnit;
/**
* 演示线程状态:TIMED_WAITING
*/
public class ThreadStateTimedWaitingDemo {
public static void main(String[] args) throws InterruptedException{
// 创建线程对象
Runnable r1 = new MyRunnable2();
String tName_1 = "my-thread-1";
Thread t1 = new Thread(r1,tName_1);
// 启动线程,休眠1秒后,获取线程状态
t1.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("1.主线程"+ Thread.currentThread().getName() +
"打印,线程:" + t1.getName() + "当前状态:" + t1.getState());
}
}
/**
* 实现Runnable接口,创建线程
*/
class MyRunnable2 implements Runnable{
public void run() {
System.out.println("线程:" + Thread.currentThread().getName() +
"准备休眠3秒:TimeUnit.SECONDS.sleep(3),等待主线程输出状态.");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.讨论分享
考考你答案: 1.你知道线程生命周期中有哪些状态吗?
1.1.在java编程语言中,线程的生命周期总共有6种状态
2.你知道各种状态对应的含义吗?
2.1.分别是:
新建:NEW
可运行:RUNNABLE
已终止:TERMINATED
阻塞:BLOCKED
等待:WAITING
计时等待:TIMED_WAITING
关于作者
王硕,网名信平,十多年软件开发经验,业余架构师,精通Java/Python/Go等,喜欢研究技术,著有《PyQt 5 快速开发与实战》《Python 3.* 全栈开发》,多个业余开源项目托管在GitHub上,欢迎微博交流。