如何将虚拟线程与ScheduledExecutorService一起使用

问题描述 投票:0回答:2

我想使用Java 19和ScheduledExecutorService中引入的虚拟线程。 我需要安排一些线程每分钟运行一次。我知道我可以使用这样的东西:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(100, Thread.ofVirtual().factory());
但看起来我被迫设置池大小。

我正在寻找与此类似的织物方法:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(Thread.ofVirtual().factory());
但我找不到它。我想遵循“每个任务一个虚拟线程”原则,而不是被迫在池中设置固定数量的线程。 你知道我是否可以以这种方式使用 ScheduledExecutorService 吗?或者存在一些适合虚拟线程的替代方案?

更新

让我详细说明我试图解决的问题。 所以我需要创建1000多个任务(我不知道确切的数字,我只能估计)。应该定期运行。有些需要每分钟运行一次,有些需要每两分钟运行一次,等等

这些任务将执行 I/O 操作(网络请求)。所以虚拟线程看起来是一个不错的选择。 但我需要一些调度功能来实现它。 通过选择 ScheduledExecutorService 我可以使用以下方法:

scheduledThreadPoolExecutor.scheduleAtFixedRate(runnableTask, 60, 60, TimeUnit.SECONDS )

如果我不需要调度,我只需创建一个像这样的执行器:

var executor = Executors.newVirtualThreadPerTaskExecutor()
但普通的 ExecutorService 不提供任何调度功能。 我将被迫自己实施调度。

所以目前我找到的最好的解决方案是:

Executors.newScheduledThreadPool(1000, Thread.ofVirtual().factory());
这通常看起来不错,但我想知道 Java API 中是否存在其他解决方案,它允许我创建 ScheduledExecutor,但我不会被迫设置线程池的大小。当我们考虑虚拟线程时,这对我来说看起来有点奇怪。

java multithreading executorservice
2个回答
3
投票

我认为你想考虑将工作卸载到虚拟线程,并使用调度程序安排工作。

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor()
ExecutorService donkey = Executors.newVirtualThreadPerTaskExecutor()

然后当您想要安排任务时。

void schedule(Runnable command, long delay, TimeUnit unit){
    scheduler.schedule( ()->donkey.execute(command), delay, unit);
}

您确实不希望您的调度线程在虚拟线程之间分割,因为您希望您的调度线程可以自由地调度更多任务。


0
投票

老实说,我认为大家都想多了。虚拟线程的主要好处是能够为每个任务启动一个虚拟线程,并使用同步 API 来实现该任务。以下是我的实现方法:

Thread.ofVirtual().start(() ->
{
  Thread.sleep(...); // Sleep until you want the task to run
  task.run();
  // Tada!
});

ScheduledExecutorService 是一个线程池。您不应该将线程池与虚拟线程一起使用。

© www.soinside.com 2019 - 2024. All rights reserved.