转载

Java线程的生命周期(线程状态)

Java 并发编程主要是通过多线程实现的,而线程的操作系统中的概念。Java 中的线程其本质上就是操作系统中的线程,但是 Java 语言对操作系统的线程做了封装。

Java 线程的生命周期,即 了解线程各个节点状态的转换机制 。了解 Java 线程生命周期有助于跟踪分析线程的状态,通过分析线程 dump 来解决死锁、饥饿、活锁的问题。

Java线程的生命周期(线程状态)

五态模型

Java线程的生命周期(线程状态)

  1. 初识状态:编程语言层面创建线程,操作系统层面未创建线程,还不允许CPU为其分配时间片。
  2. 可运行状态:操作系统层面创建线程,允许CPU为其分配之间片。
  3. 运行状态:操作系统将空闲的CPU,分配给可运行状态的线程,则线程处于运行状态。
  4. 休眠状态:运行状态的线程执行阻塞API(如I/O),或等待某个条件(如条件变量),则线程会释放CPU使用权,进入休眠状态。
  5. 终止状态:线程执行完,或者执行过程中出现异常。

Java 线程的生命周期

前面介绍了通用的线程生命周期模型——五态模型,编程语言会对操作系统对线程的操作进行封装,所以 Java 的生命周期模型和通用的线程生命周期模型有所不同,它有初识状态、运行/可运行状态、休眠状态和终止状态,其中休眠状态细分为 BLOCKED、WATING、TIMED_WATING,共 6 中状态,如下图所示:

Java线程的生命周期(线程状态)

  • NEW 初始状态
  • RUNNABLE 运行/可运行状态
  • BLOCKED 阻塞
  • WATING 无线等待
  • TIMED_WATING 有时限等待
  • TERMINATED 终止状态

Java 线程状态的转换

从 NEW 到 RUNNABLE

NEW 状态是在编程语言层面创建线程,而操作系统层面还没有创建线程。Java 创建线程有 3 种方式:

  1. 继承 Thread 类
  2. 实现 Runnable 接口
  3. 实现 Callable 接口

从 NEW 状态到 RUNNABLE 状态,就是在操作系统层面创建线程,此时需要调用 Thread.start() 方法:

MyThread myThread = new MyThread();
// 从 NEW 状态转换到 RUNNABLE 状态
myThread.start();

RUNNABLE 与 BLOCKED 状态转换

只有一种场景会触发这种转换,即线程等待 synchronized 隐式锁,此时只有一个线程能执行被 synchronized 修饰的方法或代码块,其他线程就进入 BLOCKED 状态。

当等待的线程获得 synchronized 隐式锁时,就会从 BLOCKED 状态转换为 RUNNABLE 状态。

RUNNABLE 与 WATING 状态转换

有三种场景会触发这种转换。

第一种,获取到 synchronized 隐式锁的线程调用 Object.wait() 方法,线程会从 RUNNABLE 状态转变为 WATING 状态。调用 Object.notify() 或者 Object.notifyAll() 会从 WATING 状态变为 RUNNABLE 状态。

第二种,线程调用 Thread.join()join() 是这一种线程同步的方法,当主线程调用 Thread A 的 A.join() 方法时,主线程就会从 RUNNABLE 转换为 WATING,当线程 A 执行完之后,又从 WATING 转换为 RUNNABLE。

第三种,调用 LockSupport.park() 当前线程会阻塞,线程的状态会从 RUNNABLE 转换到 WAITING。调用 LockSupport.unpark(Thread thread) 可唤醒目标线程,目标线程的状态又会从 WAITING 状态转换到 RUNNABLE。

RUNNABLE 与 TIMED_WATING 状态转换

Thread.sleep(long millis)
Object.wait(long timeout)
Thread.join(long millis)
LockSupport.parkNanos(Object blocker, long deadline)
LockSupport.parkUntil(long deadline)

从 RUNNABLE 到 TERMINATED

run()
run()
Thread.stop()
Thread.interrupt()
原文  https://segmentfault.com/a/1190000021494683
正文到此结束
Loading...