线程生命周期

线程生命周期,第1张

线程生命周期 Java线程状态

Java线程状态官方文档

Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态。

A thread can be in only one state at a given point in time. These states are virtual machine states which do not reflect any operating system thread states.

如果想要确定线程当前的状态,可以通过 java.lang.Thread#getState() 方法,并且线程在任何时刻只可能处于 1 种状态。

状态图解

NEW

线程被创建但尚未启动的状态。

线程处于此状态时,表示线程尚未开始运行,它的代码没有运行,也没有开始执行。

RUNNABLE

调用java.lang.Thread#start()方法将线程置于RUNNABLE状态,线程这时候处于 *** 作系统线程中的 READY(可运行) 状态。

线程处于此状态时,线程可能正在运行(RUNNING),也可能随时准备运行(READY)。它对应 *** 作系统线程中的READY 和 RUNNING 状态。

可运行状态(READY)的线程获得了 CPU 时间片(timeslice)后就处于 RUNNING(运行) 状态。

A multi-threaded program allocates a fixed amount of time to each individual thread. Each and every thread runs for a short while and then pauses and relinquishes the CPU to another thread, so that other threads can get a chance to run. When this happens, all such threads that are ready to run, waiting for the CPU and the currently running thread lies in runnable state.

The operating system hide the RUNNABLE and RUNNING states from the Java Virtual Machine (JVM), which sees only the RUNNABLE state.

BLOCKED

从 RUNNABLE状态进入BLOCKED状态只有一种可能,就是进入 synchronized 保护的代码时没有抢到 monitor锁,无论是进入synchronized 代码块,还是 synchronized 方法,都是一样。当处于 BLOCKED 的线程抢到 monitor 锁,就会从 BLOCKED 状态回到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 Object.wait.

WAITING

线程进入WAITING状态有三种可能性:

1、没有设置Timeout参数的Object.wait()方法。

2、没有设置Timeout参数的Thread.join()方法。

3、LockSupport.park()方法。

BLOCKED 与 WAITING 的区别是 BLOCKED 在等待其他线程释放 monitor 锁,而 WAITING 则是在等待某个条件,比如 join 的线程执行完毕,或者是 notify()/notifyAll()

A thread in the waiting state is waiting for another thread to perform a particular action. For example, a thread that has called Object.wait() on an object is waiting for another thread to call Object.notify() or Object.notifyAll() on that object. A thread that has called Thread.join() is waiting for a specified thread to terminate.

BLOCKED仅仅针对 synchronized monitor 锁,可是在 Java 中还有很多其他的锁,比如 ReentrantLock,如果线程在获取这种锁时没有抢到该锁就会进入 WAITING状态,因为本质上它执行了 LockSupport.park() 方法,所以会进入WAITING状态。同样,Object.wait() 和 Thread.join() 也会让线程进入WAITING状态。

TIMED_WAITING

在WAITING上面是 TIMED_WAITING 状态,这两个状态是非常相似的,区别仅在于有没有时间限制,TIMED_WAITING会等待超时,由系统自动唤醒,或者在超时前被唤醒信号唤醒。

以下情况会让线程进入 Timed Waiting 状态:

1、设置了时间参数的 Thread.sleep(long millis) 方法;

2、设置了时间参数的 Object.wait(long timeout) 方法;

3、设置了时间参数的 Thread.join(long millis) 方法;

4、设置了时间参数的 LockSupport.parkNanos(long nanos) 方法和 LockSupport.parkUntil(long deadline) 方法。

TERMINATED

要想进入这个状态有3种可能:

正常结束

run()或 call()方法执行完成,线程正常结束。

异常结束

线程抛出一个未捕获的 Exception 或 Error。

调用 stop 

直接调用该线程的 stop()方法来结束该线程—该方法通常容易导致死锁,不推荐使用。

状态流转

1、想要从BLOCKED状态进入RUNNABLE状态,要求线程获取monitor锁。

2、从WAITING状态流转到其他状态则比较特殊,因为首先WAITING是不限时的,也就是说无论过了多长时间它都不会主动恢复。只有当执行了 LockSupport.unpark(),或者 join 的线程运行结束,或者被中断时才可以进入RUNNABLE状态。如果其他线程调用 notify() 或 notifyAll()来唤醒它,它会直接进入BLOCKED状态,这是因为唤醒WAITING线程的线程如果调用 notify() 或 notifyAll(),要求必须首先持有该 monitor 锁,所以处于WAITING 状态的线程被唤醒时拿不到该锁,就会进入 Blocked状态,直到执行了 notify()/notifyAll() 的唤醒它的线程执行完毕并释放 monitor 锁,才可能轮到它去抢夺这把锁,如果它能抢到,就会从BLOCKED状态回到RUNNABLE状态。

3、同样在TIMED_WAITING中执行 notify() 和 notifyAll() 也是一样的道理,它们会先进入BLOCKED状态,然后抢夺锁成功后,再回到RUNNABLE状态。当然对于TIMED_WAITING而言,如果它的超时时间到了且能直接获取到锁/join的线程运行结束/被中断/调用了LockSupport.unpark(),会直接恢复到RUNNABLE状态,而无需经历BLOCKED状态。

注意点

1、线程的状态是需要按照箭头方向来走的,比如线程从 NEW 状态是不可以直接进入BLOCKED状态的,它需要先经历RUNNABLE状态。

2、线程生命周期不可逆:一旦进入RUNNABLE状态就不能回到NEW状态;一旦被终止就不可能再有任何状态的变化。所以一个线程只能有一次NEW和TERMINATED状态,只有处于中间状态才可以相互转换。

结尾

借鉴部分内容来自以下链接:

https://blog.csdn.net/qq_29860591/article/details/113726036https://blog.csdn.net/qq_29860591/article/details/113726036https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/multi-thread/Java%E5%B9%B6%E5%8F%91%E5%9F%BA%E7%A1%80%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93.md#6-%E8%AF%B4%E8%AF%B4%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%92%8C%E7%8A%B6%E6%80%81https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/multi-thread/Java%E5%B9%B6%E5%8F%91%E5%9F%BA%E7%A1%80%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93.md#6-%E8%AF%B4%E8%AF%B4%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%92%8C%E7%8A%B6%E6%80%81

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4996581.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-14
下一篇 2022-11-14

发表评论

登录后才能评论

评论列表(0条)

保存