前面介绍了线程相关的一些基本概念,也说了一个线程的创建以及销毁,那么一个线程应该是有生命周期的。这里就来看一下,一个线程一生可能会经历哪些阶段。
线程的六种状态
线程的一生可能会经过以下6种状态:
-
NEW
初始化状态,线程被创建,但是还没有调用
start
方法。线程的创建过程其实在前面从线程说起并发问题介绍线程创建的时候已经说过了,这里就不再上代码了,简单说一下使用线程的三种方式:
- 实现
Runnable
接口,重写run
方法。 - 继承
Thread
类,重写run
方法。 - 实现
Callable
接口,重写call
方法,实现带返回值的线程。
- 实现
-
RUNNABLE
运行中状态,其实这里应该是包含两种状态的,一种是就绪状态(即线程调用了
start
方法,但是不一定会立马运行,还需要等待系统OS
的调度),另一种是运行状态(即正在执行中)。 -
BLOCKED
阻塞状态,线程进入等待状态。而阻塞又分为多种情况。
- 等待阻塞:线程执行
wait
方法,JVM
将当前线程加入等待队列。 - 同步阻塞:与其他线程竞争同步锁时,由于锁已被其他线程获取,进而被
JVM
加入同步队列。 - 其他阻塞:
Thread.sleep()
、join
、IO
等操作时,JVM
会阻塞直至上述操作结束才会恢复线程。
- 等待阻塞:线程执行
-
WAITTING
等待状态,线程进入等待,需要被唤醒。
-
TIME_WAITTING
等待状态,超时以后自动返回。
-
TERMINATED
终止状态,线程执行完毕退出。
线程状态的转换
线程的一生可能会经过以上六个阶段,那么它们之间又是怎么转换的呢,这里贴上流程转换的图:
线程状态转换在图上可以看到一些操作,等到后面再慢慢介绍这些都是干嘛用的。
我们也可以通过以下代码来演示一下线程的相关状态:
public class ThreadStatus {
public static void main(String[] args) {
new Thread(() -> {
while (true) {
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "time-waiting").start();
new Thread(() -> {
while (true) {
synchronized (ThreadStatus.class) {
try {
ThreadStatus.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "waiting").start();
new Thread(new Block(),"Block-01").start();
new Thread(new Block(),"Block-02").start();
}
static class Block extends Thread {
@Override
public void run() {
synchronized (Block.class){
while(true){
try {
TimeUnit.SECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
这段代码运行起来之后,我们打开控制台,执行jps
命令,这个命令可以获得相应Java
进程的PID
。
在执行jstack PID
(PID
是我们上一步拿到的)可以得到下面的dump
信息。
. . . . . .省略部分信息
"Block-02" #16 prio=5 os_prio=31 tid=0x00007ffe1683e000 nid=0xa303 waiting for monitor entry [0x0000700006b83000]
java.lang.Thread.State: BLOCKED (on object monitor)
at top.felixu.chapter1.lifecycle.ThreadStatus$Block.run(ThreadStatus.java:44)
- waiting to lock <0x000000076b0cdb00> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus$Block)
at java.lang.Thread.run(Thread.java:748)
"Block-01" #14 prio=5 os_prio=31 tid=0x00007ffe1683a000 nid=0xa503 waiting on condition [0x0000700006a80000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at top.felixu.chapter1.lifecycle.ThreadStatus$Block.run(ThreadStatus.java:44)
- locked <0x000000076b0cdb00> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus$Block)
at java.lang.Thread.run(Thread.java:748)
"waiting" #12 prio=5 os_prio=31 tid=0x00007ffe13089000 nid=0xa603 in Object.wait() [0x000070000697d000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076aeed260> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus)
at java.lang.Object.wait(Object.java:502)
at top.felixu.chapter1.lifecycle.ThreadStatus.lambda$main$1(ThreadStatus.java:26)
- locked <0x000000076aeed260> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus)
at top.felixu.chapter1.lifecycle.ThreadStatus$$Lambda$2/668386784.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"time-waiting" #11 prio=5 os_prio=31 tid=0x00007ffe16839000 nid=0xa803 waiting on condition [0x000070000687a000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at top.felixu.chapter1.lifecycle.ThreadStatus.lambda$main$0(ThreadStatus.java:15)
at top.felixu.chapter1.lifecycle.ThreadStatus$$Lambda$1/764977973.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
. . . . . .省略部分信息
从上面的dump
可以看到线程的大部分状态了,有些状态没法从dump
的信息中看出来。
结语
不知道写点啥,拉倒吧,没有结语。
参考自《Java并发编程的艺术》
网友评论