一、哪六种?
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
二、官方源码怎么说?
我们可以看到官方源码中对于线程的状态,使用了一个枚举类。在枚举类中定义了一个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;
}
三、解读源码
NEW
新建状态,线程刚创建,还没有调用start方法时的线程状态。无需多言
RUNNABLE
可运行线程的线程状态。处于可运行状态的线程正在Java虚拟机中执行,但它可能正在等待来自操作系统(如处理器)的其他资源。
即如果当前CPU没有资源的话,其实这个线程并没有真正跑起来,而只是处于可运行的状态。因此网上很多人在讨论这个状态的时候喜欢将这个状态拆分为两种状态,一个是ready,即就绪状态,只要有资源就立马运行起来;一个是running,即此时此刻正在运行中。但是官方给出的划分中并没有直接给出两个,我觉得可能是因为,操作系统的CPU时间分片很短,只有10~20ms,所以在jvm层面在细分出来这两个状态可能没有多大意义。
BLOCKED
阻止的线程的线程状态等待监视器锁。处于阻止状态的线程正在等待监视器锁。处于synchronize同步代码块活方法中被阻塞。就是说当前线程使用了synchronized
关键字,被这个关键字修饰的代码块或者方法,都需要获取到对应的锁,在没有拿到锁之前,线程的状态就一直未BLOCKED。如果被synchronize关键字修饰的线程长期出在阻塞状态下,我们需要关心是否出现死锁的问题。
WAITING
等待线程的线程状态,不具有超时时间,区别于下面的状态的话这个就是永久等待。
通过下列的方法会使得线程进入该种状态:
Object.wait、Thread.join、LockSupport.park
TIMED_WAITING
具有指定等到时间的等待线程的线程状态。不是永久等待,达到一定时间之后会自动唤醒
通过以下方法可以使得线程进入该种状态:
Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil
TERMINATED
终止线程的线程状态。线程正常完成执行或者出现异常会进入此种状态。
四、线程切换demo
1、第一种状态切换 - 新建 -> 运行 -> 终止
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread1当前状态:" + Thread.currentThread().getState().toString());
System.out.println("thread1 执行了");
}
});
System.out.println("没调用start方法,thread1当前状态:" + thread1.getState().toString());
thread1.start();
Thread.sleep(2000L); // 等待thread1执行结束,再看状态
System.out.println("等待两秒,再看thread1当前状态:" + thread1.getState().toString());
// thread1.start(); TODO 注意,线程终止之后,再进行调用,会抛出IllegalThreadStateException异常
}
2、新建 -> 运行 -> 等待 -> 运行 -> 终止(sleep方式)
public static void main(String[] args) throws Exception {
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {// 将线程2移动到等待状态,1500后自动唤醒
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2当前状态:" + Thread.currentThread().getState().toString());
System.out.println("thread2 执行了");
}
});
System.out.println("没调用start方法,thread2当前状态:" + thread2.getState().toString());
thread2.start();
System.out.println("调用start方法,thread2当前状态:" + thread2.getState().toString());
Thread.sleep(200L); // 等待200毫秒,再看状态
System.out.println("等待200毫秒,再看thread2当前状态:" + thread2.getState().toString());
Thread.sleep(3000L); // 再等待3秒,让thread2执行完毕,再看状态
System.out.println("等待3秒,再看thread2当前状态:" + thread2.getState().toString());
}
3、新建 -> 运行 -> 阻塞 -> 运行 -> 终止
public static void main(String[] args) throws Exception {
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (ThreadStatusTest.class) {
System.out.println("thread3当前状态:" + Thread.currentThread().getState().toString());
System.out.println("thread3 执行了");
}
}
});
synchronized (ThreadStatusTest.class) {
System.out.println("没调用start方法,thread3当前状态:" + thread3.getState().toString());
thread3.start();
System.out.println("调用start方法,thread3当前状态:" + thread3.getState().toString());
Thread.sleep(200L); // 等待200毫秒,再看状态
System.out.println("等待200毫秒,再看thread3当前状态:" + thread3.getState().toString());
}
Thread.sleep(3000L); // 再等待3秒,让thread3执行完毕,再看状态
System.out.println("等待3秒,让thread3抢到锁,再看thread3当前状态:" + thread3.getState().toString());
}
最后插入一张别人画的比较好的解释了线程状态切换的图
参考图片地址:https://blog.csdn.net/pange1991/article/details/53860651