4

В моем приложении у меня есть 4 различных процесса, которые работают постоянно с небольшими паузами.Несколько newSingleThreadExecutor против newFixedThreadPool от ExecutorService

Текущая версия кода выполняет каждый процесс в отдельной старой школы резьбы:

Thread nlpAnalyzer = new Thread(() -> { 

    // infine lop for auto restore in case of crash 
    //noinspection InfiniteLoopStatement 
    while (true) { 
     try { 
      // this method should run permanently, pauses implemented internally 
      NLPAnalyzer.analyzeNLP(dbCollection); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
}); 

nlpAnalyzer.setName("im_nlpAnalyzer"); 
nlpAnalyzer.start(); 

Теперь я хотел бы реорганизовать этот код с использованием ExecutorService. Для этого я могу использовать как минимум два подхода:

  • newFixedThreadPool(numOfProc);
  • numOfProc * newSingleThreadExecutor().

Мои вопросы:

  1. Есть ли причина, почему я должен предпочесть один вариант по другому?
  2. Что более приемлемо для создания пула потоков с потоками X или генерации X newSingleThreadExecutor?
  3. Про и против каждого подхода?
+0

Вариант 1 является более распространенным и имеет минимум накладных расходов. – Spotted

+0

В другом примечании, вы можете переписать код внутри бесконечного цикла как «Runnable», который снова загружается в качестве службы-исполнителя при запуске. Таким образом, несколько задач могут выполняться даже в одном потоке. –

ответ

2

Учитывая каждую задачу является бесконечным циклом, что бы я использовал это

newCachedThreadPool(); 

Это позволило бы создать поток для каждой задачи, которая в ней нуждается (и не более)

в пользу используя один пул с несколькими пулами, вы можете отключить пул по отдельности или дать каждому потоку имя, но если вам это не нужно, это просто накладные расходы.

Примечание: вы можете изменить имя потока с помощью setName («Моя задача»), которое может быть полезно для целей отладки/профилирования.

Одним из приемов использования ExecutorService является то, что он захватывает любые неперехваченные исключения/ошибки и помещает их в возвращаемый объект Future. Часто это Future отбрасывается, что означает, что если ваша задача неожиданно умирает, она также может сделать это тихо.

Я предлагаю вам попробовать/поймать (Throwable) вне цикла и зарегистрировать его, чтобы вы могли увидеть, когда нить когда-либо неожиданно умирает. например, OutOfMemoryError

+0

Насколько я знаю, я могу назначить отдельное имя потока даже в 'newFixedThreadPool', а не только с' newSingleThreadExecutor'. Есть ли разница в производительности между define 1 'newFixedThreadPool' для потоков X или X' newSingleThreadExecutor's? –

+1

@MikeB. Вы можете назначить отдельное имя потока, но не одно, основанное на цели задачи, которая может быть более полезной. Я бы сделал все, что вы считаете более ясным, независимо от того, какое решение вы выбрали, «Thread» все еще выполняет эту работу. –

1

Я не вижу никакой пользы для опции ниже, кроме выключения отдельного исполнителя.

numOfProc * newSingleThreadExecutor() 

Но у вас есть больше возможностей. Я предпочитаю один из трех вариантов от Executors.

newFixedThreadPool 
newCachedThreadPool 
newWorkStealingPool 

см ниже SE вопросов для соответствующих запросов:

Java's Fork/Join vs ExecutorService - when to use which?

How to properly use Java Executor?

Difference between Executors.newFixedThreadPool(1) and Executors.newSingleThreadExecutor()

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