2017-02-17 3 views
2

Я написал пример кода:Почему threadpool создает только один поток?

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 неправильно.

+0

Кажется, что сегодня мы составляем отличную команду ;-) ... больше вопросов, чтобы прийти с вашей стороны? И просто из любопытства: в прошлый раз вы поддержали и приняли; на этот раз просто принять; есть ли более глубокая логика? – GhostCat

+0

Я не понимаю, почему, если я использую SynchronousQueue в моем примере - используется только один поток, но в случае newCachedThreadPool (он использует SynchrounousQueue внутри) - количество потоков отличается от 1 – gstackoverflow

+0

. Для этой части, вероятно, придется точно посмотреть на исходный код. Возможно, код, предоставленный «фабрикой», использует немного отличающийся класс очереди; там какая-то тонкая разница. – GhostCat

ответ

0

Я предполагаю ответ на такое поведение может быть укоренена в:

ThreadPoolExecutor будет автоматически регулировать размер пула (см getPoolSize()) в соответствии с границами, установленными corePoolSize (см getCorePoolSize()) и maximumPoolSize (см. getMaximumPoolSize()). Когда новая задача отправляется при выполнении метода (java.lang.Runnable), и выполняется меньше потоков corePoolSize, для обработки запроса создается новый поток, даже если другие рабочие потоки простаивают. Если существует больше, чем corePoolSize, но меньше потоков MaximumPoolSize, новый поток будет создан только в том случае, если очередь заполнена.

(from ThreadPoolExecutor javadoc).

Вещь: как спальные темы, входящие в это уравнение. Мое предложение: изменить corePoolSize от 0 до 10; и установите максимальный размер пула на 10.

+0

мой размер ядра равен 0 – gstackoverflow

+0

новый ThreadPoolExecutor (0, 100, .....) – gstackoverflow

+0

Поскольку LinkedBlockingQueue без ограничений, таким образом, очередь не заполнена в моем случае – gstackoverflow

2

Причина может быть найдена с ThreadPoolExecutor javadoc.

Любое BlockingQueue может использоваться для передачи и хранения предоставленных задач.

Использование этой очереди взаимодействует с бассейном проклейки: Если меньше, чем corePoolSize потоков выполняются, Исполнитель всегда предпочитает добавлять новый поток, а не в очередь.

Если corePoolSize или более потоки равны , Executor всегда предпочитает очередность запроса, а не , добавляя новый поток.

Если запрос не может быть поставлен в очередь, новый поток будет создан , если это не будет превышать maximumPoolSize, и в этом случае задача будет отклонена.

Поэтому, поскольку ваш corePoolSize равен 0, первый вариант не используется, и поскольку ваша очередь не ограничена, последний параметр не используется. Поэтому оставшаяся стратегия очередей - это то, что вы получаете.

Различные результаты можно увидеть, изменив corePoolSize или размером workQueue.

+0

как насчет SynchronousQueue? – gstackoverflow

+0

@gstackoverflow Как насчет этого? Вы не захотите использовать 0-мерную очередь для workQueue. – Kayaman

+0

мой дополнительный qaestion, почему, если я использую SynchronousQueue - я вижу тот же плохой результат, и я не знаю, о чем можно поставить задачу в очередь в эту очередь или нет. Действительно, после замены очереди на SynchronousQueue - я вижу старый результат (9.6) – gstackoverflow

Смежные вопросы