我正在开发一个多线程项目,我需要生成多个线程来测量我的客户端代码的端到端性能,因为我正在进行负载和性能测试 . 所以我创建了以下使用 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
}
}
Problem statement:
现在我正在阅读互联网上的一些文章 . 我发现还有 ThreadPoolExecutor
. 所以我很困惑我应该使用哪一个 .
如果我将以上代码替换为:
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
的原始代码与使用 ThreadPoolExecutor
粘贴的新代码之间的区别 . 我的一些队友说第二个(ThreadPoolExecutor)是正确的使用方式 .
谁能为我澄清一下这个?
6 回答
这是
Executors.newFixedThreadPool
的来源:如上所示,它在内部使用具有默认配置的
ThreadPoolExecutor
类 . 现在有些情况下默认配置不合适而不是LinkedBlockingQueue
需要使用优先级队列等 . 在这种情况下,调用者可以通过实例化并将所需的配置传递给它来直接处理底层ThreadPoolExecutor
.这将使您的代码更复杂,几乎没有什么好处 .
几乎没有 .
Executors
创建一个ThreadPoolExecutor来完成实际工作 .仅仅因为它更复杂并不意味着它是正确的做法 . 设计人员提供了Executors.newXxxx方法,使您的生活更简单,因为他们希望您使用这些方法 . 我建议你也使用它们 .
基本上是
2 .
在第二种情况下,您只是将maxPoolSize增加到2000,我怀疑您需要它 .
我相信RejectionHandler还有一个优势 . 纠正我,如果错了
在第一个示例中,您使用以下语句创建了仅20个线程
在第二个示例中,您已将线程限制范围设置在
20 to 2000
之间更多线程可供处理 . 但是您已将任务队列配置为无界队列 .
如果您定制了以下许多或所有参数,ThreadPoolExecutor会更有效 .
设置
max capacity for workQueue
时,RejectedExecutionHandler
会很有用,并且已提交给Executor的任务数超过workQueue
.有关详细信息,请查看ThreadPoolExecutor中的“已拒绝任务”部分 .
经过2天
GC out of memory exception
,ThreadPoolExecutor
救了我的命 . :)正如巴拉吉所说,
在我的情况下,我有很多
RejectedExecutionException
并指定(如下)丢弃政策解决了我所有的问题 .不过要小心!仅当您需要执行 all 提交给执行程序的线程时,它才有效 .
有关
ThreadPoolExecutor
的更多信息,请查看Darren's answer