public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
/**
* 程序目的:观察线程的各种状态
* created at 2020-06-26 19:09
* @author lerry
*/
class MyThread extends Thread {
@Override
public void run() {
System.out.printf("%s线程运行\n", Thread.currentThread().getName());
}
}
/**
* 分别观察创建线程后、start()后、和线程退出后的线程状态。
* 其中Thread.sleep(50);是为了等待线程执行完
*/
public class ThreadStateDemo {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.printf("创建线程后,线程的状态为:%s\n", myThread.getState());
myThread.start();
System.out.printf("调用start()方法后线程的状态为:%s\n", myThread.getState());
// 休眠50毫秒,等待MyThread线程执行完
Thread.sleep(50);
System.out.printf("再次打印线程的状态为:%s\n", myThread.getState());
}
}
创建线程后,线程的状态为:NEW 调用start()方法后线程的状态为:RUNNABLE Thread-0线程运行 再次打印线程的状态为:TERMINATED
import lombok.extern.slf4j.Slf4j;
/**
* 程序目的:观察线程的BLOCKED状态
* created at 2020-06-26 19:09
* @author lerry
*/
@Slf4j
public class ThreadBlockedStateDemo {
public static void main(String[] args) {
Thread threadA = new Thread(() -> method01(), "A-Thread");
Thread threadB = new Thread(() -> method01(), "B-Thread");
threadA.start();
threadB.start();
log.info("线程A的状态为:{}", threadA.getState());
log.info("线程B的状态为:{}", threadB.getState());
}
/**
* 停顿10毫秒、模拟方法执行耗时
*/
public static synchronized void method01() {
log.info("[{}]:开始执行主线程的方法", Thread.currentThread().getName());
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
log.info("[{}]:主线程的方法执行完毕", Thread.currentThread().getName());
}
}
2020-06-26 20:32:15.404 [A-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [A-Thread]:开始执行主线程的方法 2020-06-26 20:32:15.404 [main ] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - 线程A的状态为:RUNNABLE 2020-06-26 20:32:15.407 [main ] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - 线程B的状态为:BLOCKED 2020-06-26 20:32:15.417 [A-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [A-Thread]:主线程的方法执行完毕 2020-06-26 20:32:15.418 [B-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [B-Thread]:开始执行主线程的方法 2020-06-26 20:32:15.430 [B-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [B-Thread]:主线程的方法执行完毕
import lombok.extern.slf4j.Slf4j;
/**
* <pre>
* 程序目的:观察线程的WAITING状态
* 模拟:只有一个售票窗口的售票厅,有两个粉丝都想买票。
* 如果没有票,他们就继续等待、如果有票,则买票、然后离开售票厅。
* 其中,工作人员会补票,补票之后,粉丝就可以买到票了。
* </pre>
* created at 2020-06-26 19:09
* @author lerry
*/
@Slf4j
public class ThreadWaitingStateDemo {
public static void main(String[] args) throws InterruptedException {
Ticket ticket = new Ticket();
Thread threadA = new Thread(() -> {
synchronized (ticket) {
while (ticket.getNum() == 0) {
try {
ticket.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
ticket.buy();
}
}, "粉丝A");
Thread threadB = new Thread(() -> {
synchronized (ticket) {
while (ticket.getNum() == 0) {
try {
ticket.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
ticket.buy();
}
}, "粉丝B");
threadA.start();
threadB.start();
// 确保A和B线程都运行起来
Thread.sleep(10);
log.info("粉丝A线程的状态为:{}", threadA.getState());
log.info("粉丝B线程的状态为:{}", threadB.getState());
Thread employeeThread = new Thread(() -> {
synchronized (ticket) {
if (ticket.getNum() == 0) {
ticket.addTickt();
ticket.notifyAll();
}
}
}, "补票员");
employeeThread.start();
}
}
@Slf4j
class Ticket {
/**
* 票的张数
*/
private int num = 0;
public int getNum() {
return num;
}
public void addTickt() {
try {
Thread.sleep(2_000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
log.info("补充票");
this.num = 2;
}
/**
* 停顿10毫秒、模拟方法执行耗时
*/
public void buy() {
log.info("[{}]:购买了一张票", Thread.currentThread().getName());
log.info("[{}]:退出售票厅", Thread.currentThread().getName());
}
}
2020-06-26 21:26:37.938 [main ] INFO com.hua.threadtest.state.ThreadWaitingStateDemo - 粉丝A线程的状态为:WAITING 2020-06-26 21:26:37.945 [main ] INFO com.hua.threadtest.state.ThreadWaitingStateDemo - 粉丝B线程的状态为:WAITING 2020-06-26 21:26:39.948 [补票员 ] INFO com.hua.threadtest.state.Ticket - 补充票 2020-06-26 21:26:39.949 [粉丝B ] INFO com.hua.threadtest.state.Ticket - [粉丝B]:购买了一张票 2020-06-26 21:26:39.949 [粉丝B ] INFO com.hua.threadtest.state.Ticket - [粉丝B]:退出售票厅 2020-06-26 21:26:39.949 [粉丝A ] INFO com.hua.threadtest.state.Ticket - [粉丝A]:购买了一张票 2020-06-26 21:26:39.949 [粉丝A ] INFO com.hua.threadtest.state.Ticket - [粉丝A]:退出售票厅
2020-06-26 21:27:10.704 [main ] INFO com.hua.threadtest.state.ThreadWaitingStateDemo - 粉丝A线程的状态为:TIMED_WAITING 2020-06-26 21:27:10.709 [main ] INFO com.hua.threadtest.state.ThreadWaitingStateDemo - 粉丝B线程的状态为:TIMED_WAITING 2020-06-26 21:27:12.714 [补票员 ] INFO com.hua.threadtest.state.Ticket - 补充票 2020-06-26 21:27:12.714 [粉丝B ] INFO com.hua.threadtest.state.Ticket - [粉丝B]:购买了一张票 2020-06-26 21:27:12.714 [粉丝B ] INFO com.hua.threadtest.state.Ticket - [粉丝B]:退出售票厅 2020-06-26 21:27:12.715 [粉丝A ] INFO com.hua.threadtest.state.Ticket - [粉丝A]:购买了一张票 2020-06-26 21:27:12.715 [粉丝A ] INFO com.hua.threadtest.state.Ticket - [粉丝A]:退出售票厅
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}