Java 线程状态

Java 线程共有 6 种状态,在任意时刻只能处于其中一种状态,随着代码的执行状态也会发生变化。

线程状态

Java 线程状态定义在 Thread 类的内部枚举类 State 中,其定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 同一时刻,一个线程只能处于一种状态,这些状态是JVM虚拟机状态,
* 不反映任何操作系统的线程状态
*/
public enum State {
/**
* 线程还没有启动
*/
NEW,

/**
* 表示线程可运行。该状态表示线程正在JVM中执行,但是它可能正在
* 等待来自操作系统的其他资源,例如CPU
*/
RUNNABLE,

/**
* 该状态表示线程正在等待获取 monitor 锁,以进入 synchronized 代码块
* 或 synchronized 方法,包括被 Object.wait() 唤醒后重新进入上述代码
*/
BLOCKED,

/**
* 线程处于等待状态是由于调用了以下方法之一:
* 1. 不带超时参数的 Object.wait
* 2. 不带超时参数的 Thread.join
* 3. LockSupport.park
*
* 线程处于等待状态是在等待其他线程执行特定的操作,
* 例如:
* 1. 一个线程调用了某个对象的 Object.wait() 方法,它是在等待另外一个线程
* 在该对象上执行 Object.notify() 或者 Object.notifyAll() 方法
* 2. 一个线程调用了 Thread.join() 方法,它是在等待指定线程结束
*/
WAITING,

/**
* 线程处于超时等待状态是由于调用了以下方法之一,并且带有超时参数:
* Thread.sleep(long)
* Object.wait(long)
* Thread.join(long)
* LockSupport.parkNanos
* LockSupport.parkUntil
*/
TIMED_WAITING,

/**
* 线程已经执行完
*/
TERMINATED;
}

线程状态的转换

在特定条件下,线程的状态会发生变化。线程状态的转换和变化的条件如下图所示:

初始状态(NEW)

线程被创建完,但是还没有调用start()方法启动线程

1
2
3
4
5
6
7
8
9
10
11
12
public class StateNew {
public static void main(String[] args) {
// 创建线程对象
Thread thread = new Thread("myThread");

// 输出线程状态
System.out.println(thread.getName() + ": " + thread.getState());

// 启动线程
thread.start();
}
}

输出结果:

1
myThread: NEW

可运行状态(RUNNABLE)

表明当前线程已经在执行(RUNNING)或者在等待系统调度执行(READY)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class StateRunnable implements Runnable {
public static void main(String[] args) {
Thread thread = new Thread(new StateRunnable(), "myThread");

thread.start();
}

@Override
public void run() {
// 显示当前线程状态
showState();
}

public void showState() {
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + ": " + thread.getState());
}
}

输出结果:

1
myThread: RUNNABLE

等待状态(WAITING)

线程调用 Object.wait()Thread.join()LockSupport.park() 等方法时会进入等待状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class StateWaiting implements Runnable {
private Object object = new Object();

public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new StateWaiting(), "myThread");
thread.start();

// 主线程等待
thread.join();
}

@Override
public void run() {
synchronized (object) {
try {
// 线程等待唤醒
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

执行 jps 命令查看线程ID

1
2
3
4
4560 Jps
4545 Launcher
769 RemoteMavenServer
4546 StateWaiting

然后执行 jstack 查看线程信息

1
jstack 4546

输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"myThread" #12 prio=5 os_prio=31 tid=0x00007fbdfa13c000 nid=0x4403 in Object.wait() [0x000070000a80e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076af2ace0> (a java.lang.Object)
at java.lang.Object.wait(Object.java:502)
at com.gorden5566.demos.thread.state.StateWaiting.run(StateWaiting.java:21)
- locked <0x000000076af2ace0> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)

"main" #1 prio=5 os_prio=31 tid=0x00007fbdf8801800 nid=0x2703 in Object.wait() [0x00007000096db000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076af2ab58> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1252)
- locked <0x000000076af2ab58> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1326)
at com.gorden5566.demos.thread.state.StateWaiting.main(StateWaiting.java:14)

从中可以看出:

  1. 新创建的线程 myThread 由于执行了 object.wait() 而处于 WAITING 状态,在等待其他线程唤起
  2. main 线程由于执行了 thread.join() 而处于 WAITING 状态,在等待 myThread 执行结束

超时等待状态(TIMED_WAITING)

线程调用 Thread.sleep(long)Object.wait(long)Thread.join(long)LockSupport.parkNanosLockSupport.parkUntil 等方法时会进入超时等待状态

把上面的代码改为超时等待

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class StateTimeWaiting implements Runnable {
private Object object = new Object();

public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new StateTimeWaiting(), "myThread");
thread.start();

// 主线程等待
thread.join(1000 * 60);
}

@Override
public void run() {
synchronized (object) {
try {
// 线程等待唤醒
object.wait(1000 * 60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

查看结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"myThread" #12 prio=5 os_prio=31 tid=0x00007facf50d6800 nid=0x4103 in Object.wait() [0x000070000a3c3000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076af2b058> (a java.lang.Object)
at com.gorden5566.demos.thread.state.StateTimeWaiting.run(StateTimeWaiting.java:23)
- locked <0x000000076af2b058> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)

"main" #1 prio=5 os_prio=31 tid=0x00007facf5003800 nid=0x2703 in Object.wait() [0x0000700009290000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076af2aed0> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1260)
- locked <0x000000076af2aed0> (a java.lang.Thread)
at com.gorden5566.demos.thread.state.StateTimeWaiting.main(StateTimeWaiting.java:15)

状态变为 TIMED_WAITING

终止状态(TERMINATED)

线程已经执行完,线程对象可能还存活,但是不能再次执行

0%