2017-05-08 162 views
0

我应该在每个方法调用中创建新的ExecutorService还是每个类使用一个?在性能方面哪个是首选?ExecutorService - 在方法中创建新实例vs每个类创建一个实例

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 
    } 
} 
+2

您不会根据性能选择此选项。你根据需要选择它。你是否需要10个新线程向用户发送通知?如果只使用其中一个线程,那么拥有10个可重用线程池有什么意义?(假设这就是向用户发送通知的方法)? –

+0

用户可能与1个以上的密钥相关。但是,这不是在发布之前修改的好代码示例。 – Justas

回答

1

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

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

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

1

这取决于两个问题:

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

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

或者如果将一个threadPool分配给该类会发生什么?您是否可能遇到问题(由于线程池被用尽而阻塞)?

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

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