前文《Java多线程-基础篇-1.什么是多线程》已经说明了线程的状态以及线程状态的切换规则。本文将采用实例演示线程之间状态的切换。
1.TIME_WAITING状态
package com.lreis.learing.thread.state;
public class ThreadState_TimeWaiting extends Thread {
public static void main(String[] args) throws InterruptedException {
// 线程状态间的状态转换:NEW->RUNNABLE->TIME_WAITING->RUNNABLE->TERMINATED
System.out.println("======线程状态间的状态转换NEW->RUNNABLE->TIME_WAITING->RUNNABLE->TERMINATED======");
// 定义一个内部线程
Thread thread = new Thread(() -> {
System.out.println("2.执行thread.start()之后,线程的状态:" + Thread.currentThread().getState());
try {
// 休眠100毫秒
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("4.执行Thread.sleep(long)完成之后,线程的状态:" + Thread.currentThread().getState());
});
// 获取start()之前的状态
System.out.println("1.通过new初始化一个线程,但是还没有start()之前,线程的状态:" + thread.getState());
// 启动线程
thread.start();
// 休眠50毫秒
Thread.sleep(50);
// 因为thread1需要休眠100毫秒,所以在第50毫秒,thread1处于sleep状态
System.out.println("3.执行Thread.sleep(long)时,线程的状态:" + thread.getState());
// thread1和main线程主动休眠150毫秒,所以在第150毫秒,thread1早已执行完毕
Thread.sleep(100);
System.out.println("5.线程执行完毕之后,线程的状态:" + thread.getState() + "\n");
}
}
造成TIME_WAITING状态的方式有Thread.sleep(long)、Object.wait(long)、Object.wait(long)、join(long)、LockSupport.parkNanos(obj,long)和LockSupport.parkUtil(obj,long)。
说明
- 线程运行状态和可运行状态使用的是同一状态RUNNABLE;
- 线程调用sleep(long)后完成RUNNABLE状态到TIME_WAITING状态的切换。
2.WAITING状态
package com.lreis.learing.thread.state;
import java.util.concurrent.atomic.AtomicBoolean;
public class ThreadState_Waiting extends Thread {
public static void main(String[] args) throws InterruptedException {
// 线程状态间的状态转换:NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
System.out.println("======线程状态间的状态转换NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED======");
// 定义一个对象,用来加锁和解锁
AtomicBoolean lock = new AtomicBoolean(false);
// 定义一个内部线程
Thread thread1 = new Thread(() -> {
System.out.println("2.执行thread.start()之后,线程的状态:" + Thread.currentThread().getState());
synchronized (lock) {
try {
// thread1需要休眠100毫秒
Thread.sleep(100);
// thread1100毫秒之后,通过wait()方法释放obj对象是锁
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("4.被object.notify()方法唤醒之后,线程的状态:" + Thread.currentThread().getState());
});
// 获取start()之前的状态
System.out.println("1.通过new初始化一个线程,但是还没有start()之前,线程的状态:" + thread1.getState());
// 启动线程
thread1.start();
// main线程休眠150毫秒
Thread.sleep(150);
// 因为thread1在第100毫秒进入wait等待状态,所以第150秒肯定可以获取其状态
System.out.println("3.执行object.wait()时,线程的状态:" + thread1.getState());
// 声明另一个线程进行解锁
new Thread(() -> {
synchronized (lock) {
// 唤醒等待的线程
lock.notify();
}
}).start();
// main线程休眠10毫秒等待thread1线程能够苏醒
Thread.sleep(10);
// 获取thread1运行结束之后的状态
System.out.println("5.线程执行完毕之后,线程的状态:" + thread1.getState() + "\n");
}
}
造成WAIT状态的方式有Thread.wait()、join()、LockSupport.park()方法。
3.BLOCKED状态
package com.lreis.learing.thread.state;
import java.util.concurrent.atomic.AtomicBoolean;
public class ThreadState_Blocked {
public static void main(String[] args) throws InterruptedException {
// 线程状态间的状态转换:NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED
System.out.println("======线程状态间的状态转换NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED======");
// 定义一个对象,用来加锁和解锁
AtomicBoolean obj2 = new AtomicBoolean(false);
// 定义一个线程,先抢占了obj2对象的锁
new Thread(() -> {
synchronized (obj2) {
try {
// 第一个线程要持有锁100毫秒
Thread.sleep(100);
// 然后通过wait()方法进行等待状态,并释放obj2的对象锁
obj2.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// 定义目标线程,获取等待获取obj2的锁
Thread thread3 = new Thread(() -> {
System.out.println("2.执行thread.start()之后,线程的状态:" + Thread.currentThread().getState());
synchronized (obj2) {
try {
// thread3要持有对象锁100毫秒
Thread.sleep(100);
// 然后通过notify()方法唤醒所有在ojb2上等待的线程继续执行后续操作
obj2.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("4.阻塞结束后,线程的状态:" + Thread.currentThread().getState());
});
// 获取start()之前的状态
System.out.println("1.通过new初始化一个线程,但是还没有thread.start()之前,线程的状态:" + thread3.getState());
// 启动线程
thread3.start();
// 先等100毫秒
Thread.sleep(50);
// 第一个线程释放锁至少需要100毫秒,所以在第50毫秒时,thread3正在因等待obj的对象锁而阻塞
System.out.println("3.因为等待锁而阻塞时,线程的状态:" + thread3.getState());
// 再等300毫秒
Thread.sleep(300);
// 两个线程的执行时间加上之前等待的50毫秒以供250毫秒,所以第300毫秒,所有的线程都已经执行完毕
System.out.println("5.线程执行完毕之后,线程的状态:" + thread3.getState());
}
}
BLOCKED状态是不能拿到synchronized对象锁而处于等待状态。