图解 Java 线程生命周期

2020-08-20 15:23:42 浏览数 (1)

  • Java 线程生命周期中都包含哪些状态?
  • 生命周期中各个状态都是什么含义?
  • 状态是如何转化的?

线程的生命周期,对于多线程开发是非常重要的,也是面试中常见的问题。

下面我们就梳理一下线程的生命周期,快速理解掌握。

线程生命周期总览

这是线程生命周期的总览图:

在图中可以看到一个线程的所有状态,我们先了解一下这些状态的含义。

  • NEW - 初始状态,一个新创建的线程,还没开始执行。
  • RUNNABLE - 可执行的状态,要么是在执行,要么是一切就绪等待执行,例如等待分配CPU时间。
  • WAITING - 等待状态,等待其他的线程去执行特定的动作,没有时间限制。
  • TIMED_WAITING - 限时等待状态,等待其他的线程去执行特定的动作,这个是在一个指定的时间范围内。
  • BLOCKED - 阻塞状态,等待锁,以便进入同步块儿。
  • TERMINATED - 终止状态,线程执行结束。

如上图,这些状态大体上可以分为 2 个部分:

(1)正常过程

创建线程(NEW),然后线程做自己的工作(RUNNABLE),做完之后就终止了(TERMINATED)。

(2)非正常情况

线程执行的时候遇到了点问题,需要等待(WAITING、TIMED WAITING)一会儿,或者被别人阻塞了(BLOCKED)。

线程结束等待之后,也可能进入阻塞状态。

非正常情况结束之后,线程再继续执行自己的工作,所以箭头也好理解了。

NEW

NEW 线程是被创建出来后还没执行的。

这个状态直到调用了 start() 方法后变化。

下面的代码显示了一个 NEW 状态的线程:

代码语言:javascript复制
Thread t = new MyThread();

RUNNABLE

我们创建一个线程,然后调用了 start() 方法,那么这个线程就从 NEW 变为了 RUNNABLE 状态。

处于 RUNNABLE 状态的线程可能正在运行,也可能在等待系统为其分配资源。

JVM 中的 Thread-Scheduler(线程调度器)会为每个线程分配一个固定的执行时间,所以一个线程一次就只执行一段时间,时间到了之后,就会让其他的 RUNNABLE 状态的线程执行。

下面的代码显示了 RUNNABLE 状态:

代码语言:javascript复制
Thread t = new MyThread();
t.start();

WAITING

一个线程在等待其他线程执行特定动作的时候就处于 WAITING 状态。

调用下列方法后就会进入 WAITING 状态:

  1. object.wait()
  2. thread.join()
  3. LockSupport.park()

例如:

我们创建并启动 1个线程 threadA

threadA 又创建了 threadB,然后启动

threadA 里面调用了 threadB.join(),那么这时 threadA 就进入了 WAITING 状态,直到 threadB 执行结束。

TIMED WAITING

WAITING 一样也是等待状态,不同是 WAITING 没有时间限制,而 TIMED_WAITING 有等待时间限制。

通过下面的方法可以进入 TIMED_WAITING 状态:

  1. thread.sleep(long millis)
  2. wait(int timeout) or wait(int timeout, int nanos)
  3. thread.join(long millis*)*
  4. LockSupport.parkNanos
  5. LockSupport.parkUntil

BLOCKED

一个线程要执行的代码被其他线程锁了,所以在阻塞在这儿了,需要等待人家开锁后才能执行。

例如:

我们创建 2 个线程 threadA、threadB

有一个同步方法 A(),意味着一次只能有一个线程访问

这2个线程都要执行 A()threadA 先进去执行了,那么 threadB 就进不去了,处于 BLOCKED 状态。

TERMINATED

这是线程生命结束的状态,一个线程的结束,可能是正常执行完成了,也可能是异常终止了。

小结

最终线程的生命周期图如下:

梳理一下整体的思路:

(1)正常情况

创建线程(NEW)=> 线程工作(RUNNABLE)=> 线程终止(TERMINATED)

(2)非正常情况

线程执行时需要和其他线程配合执行,需要等待(WAITING、TIMED WAITING)

线程执行时还可能与其他线程竞争,被阻塞(BLOCKED)

非正常情况结束后,就要回到 RUNNABLE 状态,继续执行。

OK 线程生命周期的主要内容就这么多,思路梳理好之后还是很好理解的。

感谢阅读,希望对你有所帮助,欢迎点赞转发,非常感谢 !!!

0 人点赞