我已经编写了代码示例:
class Test {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executorService = new ThreadPoolExecutor(0, 100,
2L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
executorService.allowCoreThreadTimeOut(true);
CountDownLatch countDownLatch = new CountDownLatch(20);
long l = System.currentTimeMillis();
for (int i = 0; i < 20; i++) {
Thread.sleep(100);
executorService.submit(new Runnable() {
@Override
public void run() {
try {
countDownLatch.countDown();
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e);
}
}
});
}
executorService.shutdown();
countDownLatch.await();
System.out.println((System.currentTimeMillis() - l) / 100);
}
}
每100毫秒提交新任务(总任务数量 - 20)。每个任务持续时间 - 0.5秒。因此,5个任务可以并行执行,最佳执行时间为:20 * 100 + 500 = 2.5秒,池应创建5个线程
但我的实验显示9.6秒
我打开jsvisualvm
以查看池创建了多少个线程,我发现只创建了一个线程:
请更正我的threadPooll配置不正确的地方。
答案 0 :(得分:3)
原因可以从ThreadPoolExecutor javadoc找到。
任何BlockingQueue都可用于转移和保留提交的任务。
此队列的使用与池大小调整交互:如果少于 corePoolSize线程正在运行,Executor总是喜欢添加一个 新线程而不是排队。
如果是corePoolSize或更多线程 在运行时,Executor总是更喜欢排队请求而不是 添加新帖子。
如果请求无法排队,则会有新线程 创建,除非这会超过maximumPoolSize,在这种情况下, 任务将被拒绝。
因此,由于您的corePoolSize
为0,因此不使用第一个选项,并且由于您的队列不受限制,因此不使用最后一个选项。因此,剩下的排队策略就是你得到的。
通过修改corePoolSize
或workQueue
的大小,可以看到不同的结果。
答案 1 :(得分:0)
我猜测这种行为的答案可以植根于:
ThreadPoolExecutor将根据corePoolSize(请参阅getCorePoolSize())和maximumPoolSize(请参阅getMaximumPoolSize())设置的边界自动调整池大小(请参阅getPoolSize())。当在方法execute(java.lang.Runnable)中提交新任务并且运行的线程少于corePoolSize时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求。如果有多个corePoolSize但运行的maximumPoolSize线程少于maximumPoolSize,则只有在队列已满时才会创建新线程。
(来自ThreadPoolExecutor javadoc)。
事情是:睡眠线程如何进入这个等式。我的建议:将corePoolSize从0更改为10;并将最大池大小设置为10。