gpt4 book ai didi

java - 哪个ExecutorService最适合阻塞IO任务

转载 作者:行者123 更新时间:2023-12-05 01:04:22 28 4
gpt4 key购买 nike

假设我们有 n 个独立的阻塞 IO 任务,例如休息调用另一台服务器的任务。然后我们需要结合所有答案。每个任务的处理时间可以超过 10 秒。

  1. 我们可以按顺序处理,最后花费~n*10秒:

    Task1Ans task1 = service1.doSomething();
    Task2Ans task2 = service2.doSomething()
    ...
    return result;
  2. 另一种策略是使用 CompletableFuture 以并行方式处理它,并在所有任务上花费约 10 秒:

    CompletableFuture<Task1Ans> task1Cs = CompletableFuture.supplyAsync(() -> service1.doSomething(), bestExecutor);
    CompletableFuture<Task2Ans> task2Cs = CompletableFuture.supplyAsync(() -> service2.doSomething(), bestExecutor);
    return CompletableFuture.allOf(task1Cs, task2Cs)
    .thenApply(nothing -> {
    ...
    // combine task1, task2 into result object
    return result;
    }).join();

第二种方法有好处,但我不明白哪种类型的线程池最适合这种任务:

ExecutorService bestExecutor = Executors.newFixedThreadPool(30)   /// or Executors.newCachedThreadPool() or Executors.newWorkStealingPool()

我的问题是哪个 ExecutorService 最适合处理 n 并行阻塞 IO 任务。

最佳答案

在完全受 CPU 限制的任务上,使用比 CPU 内核更多的线程不会获得额外的性能。所以在这种场景下,8核/8线程CPU只需要8线程就可以发挥最大性能,多用就会损失性能。 IO 任务通常通过使用比 CPU 内核更多的线程来获得性能,因为在等待 IO 时 CPU 时间可用于做其他事情。但是,即使每个线程的 CPU 开销很低,扩展也会受到限制,因为每个线程都会占用内存,并会导致缓存/上下文切换。

鉴于您的任务受 IO 限制,并且您没有提供任何其他约束,您可能应该为每个 IO 任务运行不同的线程。您可以通过使用固定或缓存的线程池来实现这一点。

如果你的 IO 任务数量非常大(数千个以上),你应该限制你的线程池的最大大小,因为你可能有太多的线程。

如果您的任务受 CPU 限制,您应该再次将线程池限制为更小的大小。核心数可以通过以下方式动态获取:

int cores = Runtime.getRuntime().availableProcessors();

此外,正如您的 CPU 具有扩展限制一样,您的 IO 设备通常也具有扩展限制。你不应该超过这个限制,但是如果不测量就很难说限制在哪里。

关于java - 哪个ExecutorService最适合阻塞IO任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72131438/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com