写点什么

Java 培训高并发之线程的 6 种状态

作者:@零度
  • 2022 年 3 月 07 日
  • 本文字数:5581 字

    阅读完需:约 18 分钟

1、线程状态分类

线程一共有六种状态,分别为 New、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED,同一时刻只有一种状态,通过线程的 getState 方法可以获取线程的状态。

2、状态详解

Thread 的状态使用 java.lang.Thread.State 枚举表示。

2.1、状态 1:NEW

当线程被创建出来还没有被调用 start()时候的状态。

public class NewState {

public static void main(String[] args) {

Thread thread1 = new Thread("thread1");

System.out.println(thread1.getState());

}

}

输出

NEW

2.2、状态 2:RUNNABLE

当线程被调用了 start(),且处于等待操作系统分配资源(如 CPU)、等待 IO 连接、正在运行状态,即表示 Running 状态和 Ready 状态。

注:不一定被调用了 start()立刻会改变状态,还有一些准备工作,这个时候的状态是不确定的_北京java培训

public class RunnableState {

public static void main(String[] args) {

Thread thread1 = new Thread("thread1");

thread1.start();

System.out.println(thread1.getState());

}

}

输出

RUNNABLE

2.3、状态 3:BLOCKED

等待监视器锁而被阻塞的线程的线程状态,当进入 synchronized 块/方法或者在调用 wait()被唤醒/超时之后重新进入 synchronized 块/方法,但是锁被其它线程占有,这个时候被操作系统挂起,状态为阻塞状态。

阻塞状态的线程,即使调用 interrupt()方法也不会改变其状态。

下面看案例代码,thread1 持有 lock 对象的锁一直没有释放,而 thread2 也想获取 lock 对象的锁,但是锁一直被 thread1 持有者,导致 thread2 被阻塞在 @1 处,此时 thread2 的状态就是 BLOCKED 状态。

import java.util.concurrent.TimeUnit;

public class BlockedState {

static String lock = "锁";

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

synchronized (lock) {

//死循环导致 thread1 一直持有 lock 对象锁

while (true) ;

}

}

};

thread1.start();

//休眠 1 秒,让 thread1 先启动

TimeUnit.SECONDS.sleep(1);

Thread thread2 = new Thread("thread2") {

@Override

public void run() {

synchronized (lock) { //@1

System.out.println("thread2");

}

}

};

thread2.start();

System.out.println("thread1.state:" + thread1.getState());

System.out.println("thread2.state:" + thread2.getState());

}

}

运行结果

thread1.state:RUNNABLE

thread2.state:BLOCKED

2 个线程的堆栈信息,线程堆栈信息中包含了线程的详细信息,如:线程状态、线程目前执行到哪段代码了

"thread2" #13 prio=5 os_prio=0 tid=0x00000000281ec000 nid=0x878 waiting for monitor entry [0x0000000028dff000]

java.lang.Thread.State: BLOCKED (on object monitor)

at BlockedState$2.run(BlockedState.java:25)

- waiting to lock <0x00000007176b2a20> (a java.lang.String)

Locked ownable synchronizers:

- None

"thread1" #12 prio=5 os_prio=0 tid=0x00000000281ea800 nid=0x5e50 runnable [0x0000000028cff000]

java.lang.Thread.State: RUNNABLE

at BlockedState$1.run(BlockedState.java:12)

- locked <0x00000007176b2a20> (a java.lang.String)

Locked ownable synchronizers:

- None

2.4、状态 4:WAITING

无条件等待,当线程调用 wait()/join()/LockSupport.park()不加超时时间的方法之后所处的状态,如果没有被唤醒或等待的线程没有结束,那么将一直等待,当前状态的线程不会被分配 CPU 资源和持有锁.

简单理解:就是无限期等待。

导致线程处于 WAITING 有 3 中方式。

方式 1:wait()

import java.util.concurrent.TimeUnit;

public class WaitingState1 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

synchronized (WaitingState1.class) {

try {

//调用 wait 方法,让线程等待

WaitingState1.class.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

};

thread1.start();

//模拟休眠 1 秒,让 thread1 运行到 wait 方法处

TimeUnit.SECONDS.sleep(1);

System.out.println("thread.state:" + thread1.getState());

}

}

输出

thread1.state:WAITING

线程 thread1 堆栈信息

"thread1" #12 prio=5 os_prio=0 tid=0x0000000027a5d800 nid=0x1b48 in Object.wait() [0x0000000028dbe000]

java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x00000007176adc68> (a java.lang.Class for WaitingState1)

at java.lang.Object.wait(Object.java:502)

at WaitingState1$1.run(WaitingState1.java:11)

- locked <0x00000007176adc68> (a java.lang.Class for WaitingState1)

Locked ownable synchronizers:

- None

方式 2:join()

public class WaitingState2 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

while (true) ;

}

};

thread1.start();

//join 方法会让当前主线程等待 thread1 结束

thread1.join();

}

}

上面代码会导致主线程处于 WAITING 状态,下面是主线程堆栈信息,第 2 行显示主线程处于 WAITING 状态

"main" #1 prio=5 os_prio=0 tid=0x00000000035a4000 nid=0x3fbc in Object.wait() [0x000000000305f000]

java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x00000007176b0708> (a WaitingState2$1)

at java.lang.Thread.join(Thread.java:1249)

- locked <0x00000007176b0708> (a WaitingState2$1)

at java.lang.Thread.join(Thread.java:1323)

at WaitingState2.main(WaitingState2.java:14)

Locked ownable synchronizers:

- None

方式 3:LockSupport.park()

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.LockSupport;

public class WaitingState3 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

LockSupport.park();

}

};

thread1.start();

//模拟休眠 1 秒,让 thread1 运行到 park 方法处

TimeUnit.SECONDS.sleep(1);

System.out.println("thread1.state:" + thread1.getState());

}

}

输出

thread1.state:WAITING

线程 thread1 堆栈信息

"thread1" #12 prio=5 os_prio=0 tid=0x00000000287cc000 nid=0x3880 waiting on condition [0x000000002918f000]

java.lang.Thread.State: WAITING (parking)

at sun.misc.Unsafe.park(Native Method)

at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)

at WaitingState3$1.run(WaitingState3.java:9)

Locked ownable synchronizers:

- None

2.5、状态 5:TIMED_WAITING

有条件的等待,当线程调用 sleep(睡眠时间)/wait(等待时间)/join(等待时间)/ LockSupport.parkNanos(等待时间)/LockSupport.parkUntil(等待时间)方法之后所处的状态,在指定的时间没有被唤醒或者java培训等待线程没有结束,会被系统自动唤醒,正常退出。

简单点理解:有限期等待。

导致线程处于 WAITING 有 5 中方式。

方式 1:sleep(睡眠时间)

import java.util.concurrent.TimeUnit;

public class TimedWaitingState1 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

//休眠 500 秒 = 500000 毫秒

try {

Thread.sleep(500 * 1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};

thread1.start();

//模拟休眠 1 秒,让 thread1 运行到 sleep 方法处

TimeUnit.SECONDS.sleep(1);

System.out.println("thread1.state:" + thread1.getState());

}

}

输出

thread1.state:TIMED_WAITING

线程 thread1 堆栈信息,堆栈信息中可以看出是线程 sleep 方法导致线程等待的

"thread1" #12 prio=5 os_prio=0 tid=0x0000000027e1c000 nid=0x5c68 waiting on condition [0x000000002917f000]

java.lang.Thread.State: TIMED_WAITING (sleeping)

at java.lang.Thread.sleep(Native Method)

at TimedWaitingState1$1.run(TimedWaitingState1.java:10)

Locked ownable synchronizers:

- None

方式 2:wait(等待时间)

import java.util.concurrent.TimeUnit;

public class TimedWaitingState2 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

synchronized (TimedWaitingState2.class) {

try {

//调用 wait 方法,让线程等待 500 秒

TimedWaitingState2.class.wait(500 * 1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

};

thread1.start();

//模拟休眠 1 秒,让 thread1 运行到 wait 方法处

TimeUnit.SECONDS.sleep(1);

System.out.println("thread1.state:" + thread1.getState());

}

}

输出

thread1.state:TIMED_WAITING

线程 thread1 堆栈信息,堆栈信息中可以看出是线程 wait 方法导致线程等待的

"thread1" #12 prio=5 os_prio=0 tid=0x0000000028571000 nid=0x4b80 in Object.wait() [0x0000000028f2e000]

java.lang.Thread.State: TIMED_WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x00000007176ae0b8> (a java.lang.Class for TimedWaitingState2)

at TimedWaitingState2$1.run(TimedWaitingState2.java:11)

- locked <0x00000007176ae0b8> (a java.lang.Class for TimedWaitingState2)

Locked ownable synchronizers:

- None

方式 3:join(等待时间)

public class TimedWaitingState3 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

while (true) ;

}

};

thread1.start();

//join 方法会让当前主线程等待 thread1 结束,最长等待 500s,如果 500s

thread1.join(500 * 1000);

}

}

主线程堆栈信息

"main" #1 prio=5 os_prio=0 tid=0x0000000003274000 nid=0x1204 in Object.wait() [0x00000000030ee000]

java.lang.Thread.State: TIMED_WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x00000007176b0cf8> (a TimedWaitingState3$1)

at java.lang.Thread.join(Thread.java:1257)

- locked <0x00000007176b0cf8> (a TimedWaitingState3$1)

at TimedWaitingState3.main(TimedWaitingState3.java:11)

Locked ownable synchronizers:

- None

方式 4:LockSupport.parkNanos(等待时间)

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.LockSupport;

public class TimedWaitingState4 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

//等待 500 秒

LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(500));

}

};

thread1.start();

//模拟休眠 1 秒,让 thread1 运行到 parkNanos 方法处

TimeUnit.SECONDS.sleep(1);

System.out.println("thread1.state:" + thread1.getState());

}

}

输出

thread1.state:TIMED_WAITING

线程 thread1 堆栈信息

"thread1" #12 prio=5 os_prio=0 tid=0x0000000028a1e000 nid=0x455c waiting on condition [0x00000000293ff000]

java.lang.Thread.State: TIMED_WAITING (parking)

at sun.misc.Unsafe.park(Native Method)

at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:338)

at TimedWaitingState4$1.run(TimedWaitingState4.java:10)

Locked ownable synchronizers:

- None

方式 5:LockSupport.parkUntil(等待时间)

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.LockSupport;

public class TimedWaitingState5 {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

//等待 500 秒

LockSupport.parkUntil(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(500));

}

};

thread1.start();

//模拟休眠 1 秒,让 thread1 运行到 parkNanos 方法处

TimeUnit.SECONDS.sleep(1);

System.out.println("thread1.state:" + thread1.getState());

}

}

输出

thread1.state:TIMED_WAITING

线程 thread1 堆栈信息

"thread1" #12 prio=5 os_prio=0 tid=0x00000000291b2000 nid=0x3cc0 waiting on condition [0x0000000029b8f000]

java.lang.Thread.State: TIMED_WAITING (parking)

at sun.misc.Unsafe.park(Native Method)

at java.util.concurrent.locks.LockSupport.parkUntil(LockSupport.java:372)

at TimedWaitingState5$1.run(TimedWaitingState5.java:10)

Locked ownable synchronizers:

- None

2.6、状态 6:TERMINATED

执行完了 run()方法。其实这只是 Java 语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求,而在 Java 语言级别只是通过 Java 代码看到的线程状态而已。

import java.util.concurrent.TimeUnit;

public class TerminatedState {

public static void main(String[] args) throws InterruptedException {

Thread thread1 = new Thread("thread1") {

@Override

public void run() {

System.out.println(Thread.currentThread());

}

};

thread1.start();

//休眠 1 秒,等待 thread1 执行完毕

TimeUnit.SECONDS.sleep(1);

System.out.println("thread1 state:" + thread1.getState());

}

}

输出

Thread[thread1,5,main]

thread1 state:TERMINATED

3、状态转换图

这个图是本文的重点,反复看,消化理解!!!



文章来源于程序员路人

用户头像

@零度

关注

关注尚硅谷,轻松学IT 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
Java培训高并发之线程的6种状态_线程_@零度_InfoQ写作平台