网站首页 > 精选教程 正文
Java 19 中的虚拟线程由 JDK 负责调度。虚拟线程创建之后,会处于不同的状态之中。这些状态包括:
- NEW:刚被创建之后的初始状态
- STARTED:线程已启动
- RUNNING:线程运行中
- PARKING:线程尝试进入停驻状态
- PARKED:线程处于停驻状态
- PINNED:线程处于锁定状态
- RUNNABLE:线程处于可运行状态
- YIELDING:线程尝试让出运行权
- TERMINATED:线程已终止
这些状态定义在 java.lang.VirtualThread 中。
private static final int NEW = 0;
private static final int STARTED = 1;
private static final int RUNNABLE = 2; // runnable-unmounted
private static final int RUNNING = 3; // runnable-mounted
private static final int PARKING = 4;
private static final int PARKED = 5; // unmounted
private static final int PINNED = 6; // mounted
private static final int YIELDING = 7; // Thread.yield
private static final int TERMINATED = 99; // final state
这些状态的变化如下图所示
在这些状态中,比较特殊的是 PARKING、PARKED、PINNED、YIELDING 等状态。这些是虚拟线程独有的。我们知道,虚拟线程与平台线程是 M 对 N 的关系。虚拟线程需要绑定到平台线程上之后才能运行。在运行过程中,如果由于某种原因无法继续执行,可以调用 VirtualThread 的 park 方法来尝试停驻,让出运行权。如果让出成功,该虚拟线程会从平台线程上解除绑定,转为停驻状态;如果让出失败,该虚拟线程会被锁定在平台线程上,导致其他虚拟线程无法使用该平台线程。
另外一种方式是应用代码主动调用 Thread.yield 来让出运行权。如果让出成功,虚拟线程会处于 RUNNABLE 状态,等待下次调度;如果让出失败,虚拟线程仍然继续运行。
Java 19 中 java.util.concurrent.locks.LockSupport 的 park 方法,会调用虚拟线程的 park 方法。这就意味着当代码因为多线程同步的原因,而无法运行时,虚拟线程会尝试停驻。
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
try {
if (t.isVirtual()) {
VirtualThreads.park();
} else {
U.park(false, 0L);
}
} finally {
setBlocker(t, null);
}
}
当虚拟线程处于锁定状态时,平台线程被该虚拟线程完全占用,会减少 JDK 调度器中可用的平台线程数量。作为调度的 ForkJoinPool 会创建新的平台线程来作为补偿,但是数量不会超过设置的最大值。
为了提高系统的吞吐量,应该尽可能地避免虚拟线程的锁定。在执行 synchronized 方法或块时,以及执行 native 方法或外部方法时,虚拟线程必定处于锁定状态。这是因为这两种方法由 JVM 来处理,JDK 的调度器无法影响这两种方法;而 Java 多线程类库中的类就没有这个问题。它们使用的是 LockSupport 中的 park 方法。当需要等待时,虚拟线程会尝试停驻而从平台线程上解除绑定,这就释放了平台线程,允许其他虚拟线程来使用,有助于提升系统的吞吐量。从这个角度来说,把 synchronized 替换成 Java 类库中的锁,可能会提升系统的吞吐量。
有几种方式可以调试虚拟线程的锁定。首先是通过系统属性 jdk.tracePinnedThreads,把该属性的值设置为 full 或者空字符串,可以在虚拟线程锁定时,输出详细的线程堆栈信息;如果该属性的值是 short,则仅输出虚拟线程的信息。
另外一种做法是使用 JFR,并监听 VirtualThreadPinnedEvent 事件,从而分析出现线程锁定的情况。
- 上一篇: Java线程生命周期详解?
- 下一篇: Java面试必考问题:线程的生命周期
猜你喜欢
- 2024-11-18 Java并发编程线程状态转换
- 2024-11-18 Java面试必考问题:线程的生命周期
- 2024-11-18 Java线程生命周期详解?
- 2024-11-18 线程从创建最终消亡,要经历的若干状态,你了解其中的多少?
- 2024-11-18 java线程状态之WAITING(等待)
- 2024-11-18 浅谈Java线程:线程基础知识扫盲
- 2024-11-18 Java线程在各个状态下调用start方法会发生什么事情?
- 2024-11-18 为什么Java中线程没有Running状态
- 2024-11-18 阻塞模型将会使线程休眠,为什么 Java 线程状态却是 RUNNABLE?
- 2024-11-18 可动态调节参数的线程池实现
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)