可以使用每任务虚拟线程 ExecutorService 来执行 PlatformThread 吗?

ydp*_*ydp -1 java multithreading virtual-threads java-21

我知道应该使用 a 来用新的虚拟线程包装所有任务VirtualThread,而不是使用 pooling s,因为这并不能真正带来好处。Executors.newVirtualThreadPerTaskExecutor()

我想知道是否应该阻止PlatformThread使用这样的执行者执行 a ,并且通常Threads 是否完全不应该传递给执行者。

try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
  Runnable platformThread = Thread.ofPlatform().unstarted(someTask);
  executor.execute(platformThread);
}
Run Code Online (Sandbox Code Playgroud)

ThreadFactory由于执行器的原因,以这种方式创建的平台线程将被虚拟线程包装。我试图了解这是否有意义,或者通常Thread对象是否不应该传递给ExecutorServices.

Bas*_*que 6

\n

用新的虚拟线程包装我们所有的任务。

\n
\n

不,并非所有任务都应该使用虚拟线程执行。虚拟线程适用于以下任务:

\n
    \n
  • 涉及阻塞,如文件I/O、日志记录、网络调用、与数据库交互等。相反,如果任务受 CPU 限制(例如视频编码),请使用平台线程。
  • \n
  • synchronized在快速执行的少量代码周围短暂使用。内部的长杂务synchronized应该重构为使用 aReentrantLock或在平台线程中运行。(此synchronized限制可能会在 Java 21 以后的 Java 未来版本中发生变化。)
  • \n
  • 在JVM内执行。如果您的任务涉及调用本机代码(例如Java 本机接口 (JNI)),请使用平台线程。
  • \n
\n
\n

Runnable platformThread = Thread.ofPlatform().unstarted(someTask);

\n
\n

正如其他人评论的那样,您的代码实际上并不在平台线程中运行。您使用ThreadasRunnable意味着run您的任务方法将在现有执行程序服务中的新虚拟线程上执行。您的对象的方法Thread#start永远不会被调用,因此不会执行此代码的平台线程。

\n

Thread你\xe2\x80\ x99已经陷入了用作Runnable. 让Thread类实现Runnable接口是 API 中的一个缺陷,是一个令人遗憾的设计选择。

\n
\n

一般来说,Thread 对象永远不应该传递给 ExecutorServices

\n
\n

如上所述,实际上您将 a 传递Runnable给了执行者服务,而不是Thread. 您的代码从未启动您的Thread对象,从未使用任何Thread功能。

\n
\n

一般来说,线程永远不应该被传递给执行者

\n
\n

Executors框架的全部目的就是减轻我们Java程序员管理线程的负担。在现代Java中我们很少直接处理Thread

\n

专注于将任务定义为Runnable/Callable对象,并将它们提交给执行器服务。我们唯一需要考虑线程的是选择建立哪种执行程序服务:虚拟线程与平台线程,如果是平台线程,则有多少个。

\n

请记住,您可以在运行时维护多个执行程序服务:

\n
    \n
  • 为视频编码等 CPU 密集型任务保留一个由平台线程支持的执行程序服务。
  • \n
  • 为大多数其他任务保留由虚拟线程支持的另一个执行程序服务。
  • \n
\n