2015-07-21 3 views
3

Я использую ExecutorService для создания фиксированного пула потоков и запуска нескольких рабочих потоков, которые слушают что-то, что произойдет, а затем выполните свои задания. Однако иногда я хотел бы увеличить или уменьшить количество потоков, которые работают одновременно, чтобы точно настроить производительность приложения (без перезапуска приложения или уничтожения любых текущих выполняемых потоков). Должен ли я создать свой собственный пул потоков или есть способ иметь пул с изменяющимся размером, который будет обрабатывать старт/стоп работников по мере необходимости.Число потоков рабочих потоков Java

+0

'ThreadPoolExecutor' с гибким размером, вы можете сделать это –

ответ

3

Однако иногда я хотел бы, чтобы увеличить или уменьшить количество потоков, запущенные в то же время для того, чтобы точно настроить Perfomance из приложения (без перезапуска приложения или убийства любых запущенных тема).

Если вы имеете в виду динамическое изменение с помощью какого-либо инструмента или чего-то другого, то я не уверен, но вы можете поставить некоторую логику кода для управления.

Вы можете использовать java.util.concurrent.ThreadPoolExecutor и использовать CorePoolSize и MaxPoolSize свойства, чтобы иметь контроль над пул потоков.

corePoolSize и maximumPoolSize:

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

Однако прежде чем вы решите, я бы рекомендовал прочитать ниже выдержки из документов Java от ThreadPoolExecutor.

Однако программистов настоятельно рекомендуются использовать более удобные исполнитель фабричных методов Executors.newCachedThreadPool() (неограниченный поток бассейна, с автоматической мелиоративных резьбой), Executors.newFixedThreadPool (INT) (фиксированные size thread pool) и Executors.newSingleThreadExecutor() (одиночный фоновый поток), который предустановляет настройки для наиболее распространенных сценариев использования.


Пример кода:
см ниже примере кода. Большинство вещей вы можете понять, прочитав код и просматривая документы Java. Тем не менее, то, что не может быть очевидным является тот факт, что

  • мы использовали ArrayBlockingQueue для получение ограниченной очереди 20 емкости (вы можете принять решение о емкости очереди согласно вашему требованию). Итак, как только в очереди будет запущено более 20 задач, будут созданы новые потоки, но до максимума maxPoolSize.
  • Основываясь на нагрузке, мы увеличиваем количество потоков пулов ядра, что означает, что больше потоков будет обрабатывать ваши задачи, поэтому шансы на получение очередей задач меньше. Но вы также можете играть с maxPoolSize.

Вы можете прочитать раздел «Очередь» ThreadPoolExecutor и решить другую очередь, согласно вашему требованию.

ThreadPoolExecutor.setCorePoolSize(int)
Устанавливает число сердечников резьбы. Это переопределяет любое значение, заданное в конструкторе. Если новое значение меньше текущего значения, превышение существующих потоков будет прекращено, когда они станут свободными. Если больше, новых потоков, при необходимости, начнется выполнение любых задач в очереди.

//Read Java docs for details about construcutor... 
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 100, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20)); 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      //Do your task... 
     } 
    }; 

    executeTasks(poolExecutor, runnable, false, false); //Compute last 2 parameters as you need and pass on required values. 

public static void executeTasks(ThreadPoolExecutor poolExecutor, Runnable runnable, boolean isUnderLoad, boolean isOverLoad){ 
    if(isOverLoad && isUnderLoad){ 
     //Handle this situation, this should not be allowed, probably a coding bug can result this... 
    } 
    poolExecutor.submit(runnable); 
    if(isUnderLoad){ 
     poolExecutor.setCorePoolSize(5); 
    } 
    if(isOverLoad){ 
     poolExecutor.setCorePoolSize(20); 
    } 
} 
+0

Задачи работает бесконечно, как они подключаются к очереди и ожидания запросов на обработку, поэтому нативный реализация не может быть путь, однако я реализую настраиваемый пул задач, который будет обрабатывать потоки таким же образом, как и java api, и будет отправлять им сигналы об удалении или при необходимости запускать новые потоки. Возможно, исполнители могут справиться с такими ситуациями, но я не хочу переписывать весь проект, просто добавляя динамические пулы потоков. –

+0

Если вы собираетесь создавать свой собственный пул потоков, тогда вам нужно много вопросов, которые вам нужно позаботиться, и это смелый и смелый шаг. В любом случае, если у вас бесконечно запущенные задачи, то вам обязательно понадобится «LinkedBlockingDeque». – hagrawal

1

ThreadPoolExecutor динамически увеличивает и сокращает количество потоков. Убедитесь, что вы правильно задали размер пула. CorePoolSize определяет максимальное количество потоков, которые порождаются. MaxPoolSize входит в игру, когда BlockingQueue определен конечного размера. Когда у вас есть конечный размер очереди, новые потоки создаются для каждой новой заданной задачи, пока она не достигнет размера ядра. Если количество запросов в инкрементах очереди за конечным размером очереди, новые потоки порождаются до достижения MaxPoolSize.

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