媒体报道

首页-玩家时代2娱乐-玩家时代2平台【注册登陆】

2022-10-29 16:09:52 heminbo888 0

首页-玩家时代2娱乐-玩家时代2平台【注册登陆】报道,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-unmountedprivate static final int RUNNING= 3; // runnable-mountedprivate static final int PARKING= 4;private static final int PARKED = 5; // unmountedprivate static final int PINNED = 6; // mountedprivate static final int YIELDING = 7; // Thread.yieldprivate 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 事件,从而分析出现线程锁定的情况。