ExectuorService与ThreadPoolExecutor(使用LinkedBlockingQueue)

我正在开发一个Multithreaded项目,在该项目中,我需要生成多个线程来测量我的客户端代码的端到端性能,因为我正在进行负载和性能testing。 所以我创build了下面使用ExecutorService代码 –

下面是使用ExecutorService的代码 –

 public class MultithreadingExample { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(20); for (int i = 0; i < 100; i++) { executor.submit(new NewTask()); } executor.shutdown(); executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); } } class NewTask implements Runnable { @Override public void run() { //Measure the end to end latency of my client code } } 

问题陈述:-

现在我正在网上阅读一些文章。 我发现有 –

ThreadPoolExecutor也是如此。 所以我很困惑我应该使用哪一个。

如果我从我的上面的代码replace –

 ExecutorService executor = Executors.newFixedThreadPool(20); for (int i = 0; i < 100; i++) { executor.submit(new NewTask()); } 

至-

 BlockingQueue<Runnable> threadPool = new LinkedBlockingQueue<Runnable>(); ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, TimeUnit.MILLISECONDS, threadPool); tpExecutor.prestartAllCoreThreads(); for (int i = 0; i < 100; i++) { tpExecutor.execute(new NewTask()); } 

那么这将有所作为? 我想了解我使用ExecutorService原始代码和我使用ThreadPoolExectuor粘贴的新代码之间有什么区别? 我的一些队友说第二个(ThreadPoolExecutor)是正确的使用方法?

任何人都可以为我澄清这件事吗? 谢谢您的帮助。

这里是Executors.newFixedThreadPool的来源:

  public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } 

它在内部使用具有默认configuration的ThreadPoolExecutor类,如上所见。 现在有些情况下,默认configuration不适合,而不是LinkedBlockingQueue需要使用优先级队列等。在这种情况下,调用者可以通过实例化并传递所需的configuration直接在底层的ThreadPoolExecutor上工作。

那么这将有所作为?

这会让你的代码更加复杂,而且收益不大。

我想了解我使用ExecutorService的原始代码和我使用ThreadPoolExectuor粘贴的新代码之间有什么区别?

一无所有 Executors创build一个ThreadPoolExecutor来完成真正的工作。

我的一些队友说第二个(ThreadPoolExecutor)是正确的使用方法?

仅仅因为它更复杂并不意味着这是正确的事情。 devise人员提供了Executors.newXxxx方法,使您的生活更简单,因为他们期望您使用这些方法。 我build议你也使用它们。

  1. 执行者#newFixedThreadPool(int nThreads)

     ExecutorService executor = Executors.newFixedThreadPool(20); 

基本上是

  return new ThreadPoolExecutor(20, 20, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); 

2。

 BlockingQueue<Runnable> threadPool = new LinkedBlockingQueue<Runnable>(); ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, TimeUnit.MILLISECONDS, threadPool); 

在第二种情况下,你只是将maxPoolSize增加到2000,我怀疑你会需要。

我相信RejectionHandler还有一个好处。 纠正我,如果错了

经过2天GC out of memory exceptionThreadPoolExecutor救了我一命。 🙂

巴拉吉说,

RejectionHandler还有另一个优势。

在我的情况下,我有很多RejectedExecutionException并指定(如下)丢弃策略解决了我所有的问题。

 private ThreadPoolExecutor executor = new ThreadPoolExecutor(1, cpus, 1, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.DiscardPolicy()); 

不过要小心! 只有当你不需要执行你提交给执行者的所有线程时,它才能工作。

有关ThreadPoolExecutor更多信息,请查看Darren的答案

在第一个例子中,你用下面的语句创build了20个线程

 ExecutorService executor = Executors.newFixedThreadPool(20); 

在第二个示例中,您已将线程限制范围设置在20 to 2000之间

  ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, TimeUnit.MILLISECONDS,threadPool); 

更多的线程可用于处理。 但是您已将任务队列configuration为无限队列。

ThreadPoolExecutor会更有效,如果你已经定制了许多或全部下面的参数。

 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) 

当您max capacity for workQueue设置max capacity for workQueue时, RejectedExecutionHandler将会很有用,并且已经提交给Executor的任务数量大于workQueue容量。

查看ThreadPoolExecutor中的Rejected tasks部分以获取更多详细信息。