ExecutorService - 在方法中创建新实例,每个类创建一个实例

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

我应该在每个方法调用中创建新的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
    }
}
java multithreading concurrency threadpool executorservice
2个回答
1
投票

在你的第一个代码片段中,ExecutorService是本地的,即在每次方法调用时创建一个新的ExecutorService,并在方法结束时终止ExecutorService。因此,当方法下次运行时,线程不会被重用。在第二个片段中,只要ExecutorService实例存活,就会保留NotificationService及其线程。正如您所看到的,不仅有更少的ExecutorService实例可用于GC,但创建的线程较少,可以重复使用。作为额外的奖励,第二种方法在创建ExecutorService之后不会产生任何没有预热的线程。

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

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


1
投票

这取决于两个问题:

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

你真的需要10个线程来解决函数中的问题吗?你需要能够两次处理这个函数(从而给它提供20个线程)吗?你有这样的资源吗?

或者如果你将threadPool分配给类会发生什么?你可能会遇到这样的问题(由于线程池被用完而阻塞)?

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

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

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