为什么threadpool只创建一个线程?

时间:2017-02-17 11:39:30

标签: java multithreading concurrency threadpool jvisualvm

我已经编写了代码示例:

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个线程

enter image description here

但我的实验显示9.6秒 我打开jsvisualvm以查看池创建了多少个线程,我发现只创建了一个线程:

enter image description here

请更正我的threadPooll配置不正确的地方。

2 个答案:

答案 0 :(得分:3)

原因可以从ThreadPoolExecutor javadoc找到。

  

任何BlockingQueue都可用于转移和保留提交的任务。

     

此队列的使用与池大小调整交互:如果少于   corePoolSize线程正在运行,Executor总是喜欢添加一个   新线程而不是排队。

     

如果是corePoolSize或更多线程   在运行时,Executor总是更喜欢排队请求而不是   添加新帖子。

     

如果请求无法排队,则会有新线程   创建,除非这会超过maximumPoolSize,在这种情况下,   任务将被拒绝。

因此,由于您的corePoolSize为0,因此不使用第一个选项,并且由于您的队列不受限制,因此不使用最后一个选项。因此,剩下的排队策略就是你得到的。

通过修改corePoolSizeworkQueue的大小,可以看到不同的结果。

答案 1 :(得分:0)

猜测这种行为的答案可以植根于:

ThreadPoolExecutor将根据corePoolSize(请参阅getCorePoolSize())和maximumPoolSize(请参阅getMaximumPoolSize())设置的边界自动调整池大小(请参阅getPoolSize())。当在方法execute(java.lang.Runnable)中提交新任务并且运行的线程少于corePoolSize时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求。如果有多个corePoolSize但运行的maximumPoolSize线程少于maximumPoolSize,则只有在队列已满时才会创建新线程。

(来自ThreadPoolExecutor javadoc)。

事情是:睡眠线程如何进入这个等式。我的建议:将corePoolSize从0更改为10;并将最大池大小设置为10。