前言
上一篇博客介绍了线程如何正确停止,这一篇博客开始介绍线程的生命周期,也是面试中常说的线程的几种状态,同时针对这几种状态的转换我们做一个总结。
哪几种状态
关于线程到底有哪几种状态,看过一些总结,实在是太杂了,说啥的都有。甚至有些博客文章中总结图里头,状态的名称都不一样。其实在Thread类的源码中,针对线程有几种状态,都一一定义了对应的枚举类型,具体如下,可以根据这个总结出Java中线程的几种状态
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
权威的结论——Java线程存在6种状态
状态 | 具体含义 |
---|---|
NEW | 对应的线程对象只是New出来了,还没有调用start方法 |
RUNNABLE | 正在执行的,或者在等待CPU调度执行的线程,都为Runnable的状态 |
BLOCKED | 当一个线程想进入到synchronize修饰的代码块,但是无法获取锁的时候的状态,即为BLOCKED状态 (BLOCKED的状态特指进入synchronize时阻塞的状态) |
WAITING | 因为调用Object.wait(),Thread.join(),LockSupport.park()之后,线程进入的阻塞状态,这个时候线程等待其他线程唤醒 |
TIMED_WAITING | 因为调用sleep(),Object.wait(long),join(long),LockSupport.parkNanos,LockSupport.parkUntil等方法进入到的计时等待状态,时间到了之后,线程自动被唤醒 |
TERMINATED | 线程的终止状态,线程运行完毕会进入到该状态 |
需要说明的是,Java中的线程状态只有这6种,没有其他的相关说法。
状态转换图
在上面的基础上,我们再绘制线程的状态转换图
相关代码实例
关于NEW、Runnable、Terminated状态的实例
/**
* autor:liman
* createtime:2021/9/11
* comment:展示线程的new runnable terminated状态
*/
@Slf4j
public class NewRunnableTerminated implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(i);
}
System.out.println(Thread.currentThread().getState());
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new NewRunnableTerminated());
System.out.println(thread.getState());//NEW
thread.start();
System.out.println(thread.getState());//刚开始,不一定有资源,也是RUNNABLE
Thread.sleep(5);
System.out.println(thread.getState());//打印线程正在运行的状态也是RUNNABLE
Thread.sleep(10);
System.out.println(thread.getState());//TERMINATED
}
}
之前很多资料上还介绍过,线程运行中和等待运行不是一个状态,上面的实例来看并不是这样。
关于BLOCKED、WAITING、TIME_WAITING三个状态的实例
/**
* autor:liman
* createtime:2021/9/11
* comment:演示线程 blocked waiting TimeWaiting的三种状态
*/
@Slf4j
public class BlockedWaitingTimedWaiting implements Runnable{
@Override
public void run() {
sync();
}
private synchronized void sync(){
try {
Thread.sleep(1000);//sleep的状态是一种TIMED_WAITING的状态
wait();//线程执行完sleep,就会进入到wait状态
} catch (InterruptedException e) {
//虽然不应该在子方法中处理中断异常,但为了演示,这里就随意了
e.printStackTrace();
}
}
public static void main(String[] args) {
BlockedWaitingTimedWaiting runnable = new BlockedWaitingTimedWaiting();
Thread thread1 = new Thread(runnable);
thread1.start();
Thread thread2 = new Thread(runnable);
thread2.start();
try {
//主线程暂停一下,以便拿到线程最新的状态
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//打印出TIME_WAITING,因为线程1正在sleep
log.info("线程1当前的状态为:{}",thread1.getState());
//线程2想拿到sync的锁,但是拿不到,这里线程2就是BLOCKED状态
log.info("线程2当前的状态为:{}",thread2.getState());
try {
//主线程暂停一下,以便线程1进入到wait状态线程最新的状态
Thread.sleep(1300);
} catch (InterruptedException e) {
e.printStackTrace();
}
//由于调用了wait方法,这里线程1就是wait状态
log.info("线程1当前的状态为:{}",thread1.getState());
}
}
运行结果如下:
一些面试题
1、线程有哪几种状态(线程的生命周期是什么)
6种,对应图来回答即可,需要注意的是并不存在什么所谓的Running状态。
2、阻塞只是指的BLOCKED么?
不仅仅是BLOCKED状态,一般情况下,BLOCKED状态,WAITING状态,TIME_WAITING状态都称为阻塞状态
总结
简单总结了一下线程的几种状态,下一个小结会总结Thread类中的一些方法,比如wait和join等。