【问题标题】:ExecutorService - create new instances in method vs one per classExecutorService - 在方法中创建新实例而不是每个类一个
【发布时间】:2017-10-06 03:08:42
【问题描述】:

我应该在每个方法调用中创建新的 ExecutorService 还是每个类都使用一个?就性能而言,哪个是首选?

public class NotificationService {

    public void sendNotification(User recipient) {

        ExecutorService notificationsPool = Executors.newFixedThreadPool(10);

        // code

        notificationsPool.shutdown();
    }
}

或者

public class NotificationService {

    ExecutorService notificationsPool = Executors.newFixedThreadPool(10);

    public void sendNotification(User recipient) {

        // code
    }
}

【问题讨论】:

  • 你不会根据性能选择这个。您根据需要选择此选项。您是否需要 10 个新线程才能向用户发送通知?如果你只使用其中一个,只使用一次(假设这是向用户发送通知会做的事情),那么拥有 10 个可重用线程池有什么意义?
  • 用户可能与超过 1 个键相关。但是,在发布之前修改的代码示例不是很好。

标签: java multithreading concurrency threadpool executorservice


【解决方案1】:

在您的第一个代码 sn-p 中,ExecutorService 是本地的,即在每个方法调用上创建一个新的ExecutorService,而ExecutorService 在方法结束时终止。因此,当方法下次运行时,线程不会被重用。在第二个 sn-p 中,只要 NotificationService 实例还活着,ExecutorService 及其线程就会被保留。如您所见,不仅要进行 GC 处理的 ExecutorService 实例更少,而且要创建的线程也更少,它们可以被重用。作为额外的奖励,在创建ExecutorService 之后,第二种方法不会为线程创建产生任何预热时间。

如果您有多个NotificationService 实例,则应将notificationsPool 声明为static,以便在所有实例之间共享池及其线程。

如果所需的线程数量因必须发送的通知数量而异,请使用缓存线程池 (ExecutorService#newCachedThreadPool()),可能有上限。

【讨论】:

    【解决方案2】:

    这取决于两个问题:

    • 您需要什么级别的并行化?
    • 您可以接受多少开销?

    你真的需要10个线程来解决函数中的问题吗?您是否需要能够两次处理该函数(从而为其提供 20 个线程)?你有资源吗?

    或者如果你为类分配一个线程池会发生什么?这样做可能会遇到问题(由于线程池用完而阻塞)?

    如果有足够的资源,如果要解决的任务足够大,可以证明每次调用函数时创建该执行程序的开销是合理的,那么选项 1 可能会更快。虽然老实说,我几乎无法想象一个如此强烈的通知。

    因此,如果没有更多信息,我将指向选项 2(当然假设它是静态的)。您也可以看看新的 WorkStealingPool,它可能会帮助您使用精确的并行度。

    【讨论】:

      猜你喜欢
      • 2016-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      • 2012-10-07
      • 1970-01-01
      • 1970-01-01
      • 2022-07-21
      相关资源
      最近更新 更多