原文地址:Java线程状态
Java的线程状态定义在Thread.State枚举里,源码如下:
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
源码显示总共有六种线程状态:
状态 | 解释 |
---|---|
NEW | 新建状态 |
RUNNABLE | 可运行状态 |
BLOCKED | 阻塞状态 |
WAITING | 等待状态 |
TIMED_WAITING | 限时等待状态(即时间一到跳出等待) |
TERMINATED | 终止状态(被中断或正常结束) |
线程的状态切换总体上如下:
括号中的状态可有可无,看代码中的具体操作,而新建、可运行、终止状态是线程必然会经历的状态。“新建”和“终止”状态分别为起始和结束状态,这两种状态和“可运行”状态之间的关系是不可逆的。其他状态均能和“可运行”状态相互转换。
代码展示不同的线程状态的切换:
1.NEW->RUNNABLE->TERMINATED
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
/**
* @Description NEW->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRT {
public static void main(String[] args) {
Thread thread=new Thread(ThreadStateNRT::printThreadStatus);
log.info(thread.getName()+ ":" + thread.getState());
thread.start();
//等待线程执行完毕。
try {
thread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
log.info(thread.getName()+ ":" + thread.getState());
}
private static void printThreadStatus() {
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
}
运行打印结果如下:
18:01:55.558 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRT - Thread-0:NEW
18:01:55.562 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRT - Thread-0:RUNNABLE
18:01:55.562 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRT - Thread-0:TERMINATED
2.NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
/**
* @Description NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRBRT {
//锁
private static final Object lock=new Object();
//锁定标志
private static volatile boolean lockFlag=true;
//执行顺序
private static volatile int order=0;
public static void main(String[] args) {
//辅助线程,制造synchronized状态。
Thread assistantThread = new Thread(ThreadStateNRBRT::run1);
assistantThread.start();
try {
//保证assistantThread先执行。
Thread.sleep(10);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
Thread showThread = new Thread(ThreadStateNRBRT::run2);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
//因为无法判断显示线程何时执行,所以循环直到显示线程执行。
while (true){
if(showThread.getState()==Thread.State.BLOCKED){
log.info(showThread.getName()+ ":" + Thread.State.BLOCKED);
lockFlag=false;
break;
}
}
//等待两个线程执行完毕。
try {
assistantThread.join();
showThread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run1() {
int i = 0 ;
while (i < 1000) {
//保证先进入同步范围。
if (order == 0) {
//锁定一定时间
synchronized (lock){
//启动另一个同步
order=1;
while (lockFlag) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
}
}
}
i++;
}
}
private static void run2() {
int i = 0;
while (i < 1000) {
//保证后进入同步范围。
if (order == 1) {
synchronized (lock){
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
break;
}
i++;
}
}
}
运行结果如下:
18:04:49.345 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:NEW
18:04:49.349 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:RUNNABLE
18:04:49.349 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:BLOCKED
18:04:50.335 [Thread-1] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:RUNNABLE
18:04:50.335 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRBRT - Thread-1:TERMINATED
3.NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
能造成WAITING状态的行为有多种:
方法 | 运用 |
---|---|
wait() | 同步代码块/方法中调用锁对象的wait()方法 |
join() | 线程对象调用join()方法 |
park() | 直接调用LockSupport的静态方法park() |
lock() | 调用Lock实现类的对象的lock()方法 |
await() | 调用Condition实现类的对象的await() |
下面展示当中的一些场景:
1.wait()
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
/**
* @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRWRT {
//锁
private static final Object lock=new Object();
public static void main(String[] args) {
//展示线程
Thread showThread = new Thread(ThreadStateNRWRT::run);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
//循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程唤醒等待线程。
while (true){
if(showThread.getState()==Thread.State.WAITING){
log.info(showThread.getName()+ ":" + showThread.getState());
break;
}
}
synchronized (lock){
lock.notifyAll();
}
try {
showThread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run() {
//等待
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
synchronized (lock){
try {
lock.wait();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
}
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
}
运行结果为:
18:49:17.933 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:NEW
18:49:17.936 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:RUNNABLE
18:49:18.942 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:WAITING
18:49:18.942 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:RUNNABLE
18:49:18.942 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRT - Thread-0:TERMINATED
2.lock()
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRWRTLock {
//锁
private static Lock lock=new ReentrantLock();
//锁定标志
private static volatile boolean lockFlag=true;
//执行顺序
private static volatile int order=0;
public static void main(String[] args) {
//展示线程
Thread showThread = new Thread(ThreadStateNRWRTLock::run1);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
//辅助线程,制造synchronized状态。
Thread assistantThread = new Thread(ThreadStateNRWRTLock::run2);
assistantThread.start();
//循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程退出同步。
while (true){
if(showThread.getState()==Thread.State.WAITING){
log.info(showThread.getName()+ ":" + showThread.getState());
lockFlag=false;
break;
}
}
try {
showThread.join();
assistantThread.join();
} catch (InterruptedException e) {
log.trace(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run2() {
while (true) {
//保证先进入同步范围。
if (order == 0) {
//加锁
lock.lock();
try {
order=1;
while (lockFlag) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
}
}finally {
lock.unlock();
}
break;
}
}
}
private static void run1() {
while (true){
//保证后进入同步范围。
if (order==1){
lock.lock();
try{
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}finally {
lock.unlock();
}
break;
}
}
}
}
运行结果为:
18:51:27.696 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:NEW
18:51:27.700 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:RUNNABLE
18:51:27.701 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:WAITING
18:51:27.711 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:RUNNABLE
18:51:27.711 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLock - Thread-0:TERMINATED
3.await()
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRWRTCondition {
//锁
private static Lock lock=new ReentrantLock();
private static Condition condition=lock.newCondition();
public static void main(String[] args) {
//展示线程
Thread showThread = new Thread(ThreadStateNRWRTCondition::run);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
//循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程唤醒等待线程。
while (true){
if(showThread.getState()==Thread.State.WAITING){
log.info(showThread.getName()+ ":" + showThread.getState());
break;
}
}
lock.lock();
try{
condition.signal();
}finally {
lock.unlock();
}
try {
showThread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run() {
//等待
lock.lock();
try{
try {
condition.await();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
}finally {
lock.unlock();
}
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
}
运行结果为:
18:53:13.367 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:NEW
18:53:13.370 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:RUNNABLE
18:53:13.370 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:WAITING
18:53:13.371 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:RUNNABLE
18:53:13.371 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTCondition - Thread-0:TERMINATED
4.park()
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.LockSupport;
/**
* @Description NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRWRTLockSupport {
public static void main(String[] args) {
//展示线程
Thread showThread = new Thread(ThreadStateNRWRTLockSupport::run);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
//循环读取展示线程状态,直到读到展示线程状态为WAITING,才让辅助线程唤醒等待线程。
while (true){
if(showThread.getState()==Thread.State.WAITING){
log.info(showThread.getName()+ ":" + showThread.getState());
break;
}
}
LockSupport.unpark(showThread);
try {
showThread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run() {
//等待
try {
Thread.sleep(100);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
LockSupport.park();
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
}
运行结果为:
18:54:02.446 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:NEW
18:54:02.449 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:RUNNABLE
18:54:02.552 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:WAITING
18:54:02.552 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:RUNNABLE
18:54:02.552 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRWRTLockSupport - Thread-0:TERMINATED
不难发现以上例子中,线程的状态转换都是一致的,都是
NEW->RUNNABLE->WAITING->RUNNABLE->TERMINATED
4.NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
能造成TIMED_WAITING状态的行为有多种:
方法 | 运用 |
---|---|
wait(long timeout) | 同步代码块/方法中调用锁对象的wait(long timeout)方法 |
join(long millis) | 线程对象调用join(long millis)方法 |
parkNanos(long nanos) | 直接调用LockSupport的静态方法parkNanos(long nanos) |
parkUntil(long deadline) | 直接调用LockSupport的静态方法parkUntil(long deadline) |
await(long time, TimeUnit unit) | 调用Condition实现类的对象的await(long time, TimeUnit unit)方法 |
这里展示2种:
1.wait(long timeout)
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
/**
* @Description NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRTWRT {
//锁
private static final Object lock=new Object();
public static void main(String[] args) {
//展示线程
Thread showThread = new Thread(ThreadStateNRTWRT::run);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
while (true){
if(showThread.getState()==Thread.State.TIMED_WAITING){
log.info(showThread.getName()+ ":" + showThread.getState());
break;
}
}
try {
showThread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run() {
//等待
synchronized (lock){
try {
Thread.sleep(100);
lock.wait(1);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
}
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
}
运行结果为:
19:08:46.182 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:NEW
19:08:46.185 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:RUNNABLE
19:08:46.185 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:TIMED_WAITING
19:08:46.291 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:RUNNABLE
19:08:46.291 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRT - Thread-0:TERMINATED
2.await(long time, TimeUnit unit)
package com.zaomianbao.java8.thread;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Description NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
* @Author zaomianbao
* @Date 2019/5/31
**/
@Slf4j
public class ThreadStateNRTWRTCondition {
//锁
private static Lock lock=new ReentrantLock();
private static Condition condition=lock.newCondition();
public static void main(String[] args) {
//展示线程
Thread showThread = new Thread(ThreadStateNRTWRTCondition::run);
log.info(showThread.getName()+ ":" + showThread.getState());
showThread.start();
log.info(showThread.getName()+ ":" + showThread.getState());
//循环读取展示线程状态,直到读到展示线程状态为TIMED_WAITING。
while (true){
if(Thread.State.TIMED_WAITING==showThread.getState()){
log.info(showThread.getName()+ ":" + showThread.getState());
break;
}
}
try {
showThread.join();
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
//线程执行完毕打印状态。
log.info(showThread.getName()+ ":" + showThread.getState());
}
private static void run() {
//等待
try {
Thread.sleep(100);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
lock.lock();
try{
try {
if (condition.await(1, TimeUnit.MILLISECONDS)){
log.info("及时返回释放");
}else {
log.info("超时未返回释放");
}
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
Thread.currentThread().interrupt();
}
}finally {
lock.unlock();
}
log.info(Thread.currentThread().getName()+ ":" + Thread.currentThread().getState());
}
}
运行结果为:
19:09:36.889 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:NEW
19:09:36.893 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:RUNNABLE
19:09:36.893 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:TIMED_WAITING
19:09:36.996 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - 超时未返回释放
19:09:36.996 [Thread-0] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:RUNNABLE
19:09:36.996 [main] INFO com.zaomianbao.java8.thread.ThreadStateNRTWRTCondition - Thread-0:TERMINATED
不难发现以上例子中,线程的状态转换都是一致的,都是
NEW->RUNNABLE->TIMED_WAITING->RUNNABLE->TERMINATED
参考:
1.https://segmentfault.com/a/1190000016197831?utm_source=tag-newest
2.https://www.cnblogs.com/happy-coder/p/6587092.html
3.https://www.cnblogs.com/hejing-swust/p/8038263.html
4.https://blog.csdn.net/pange1991/article/details/53860651