повторное использование потока Java

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

Я вижу в документе Executors класс:

Создает пул потоков, который создает новые потоки по мере необходимости, но снова использует ранее созданные потоки, когда они доступны.

Следите за словом 'повторное использование'.

Как пулы потоков 'снова используют' потоки?

54
задан Andrew Tobilko 20 February 2018 в 00:40
поделиться

3 ответа

Кажется, я понял, что вас смущает, поэтому вот мой более пространный ответ: терминология немного вводит в заблуждение (очевидно, иначе вы бы не задавали этот вопрос, специально делая акцент на "повторном использовании"):

Как пулы потоков "повторно используют" потоки?

Происходит то, что один поток может использоваться для обработки нескольких задач (обычно передаваемых как Runnable, но это зависит от вашего "исполнителя": стандартные исполнители принимают Runnable, но вы можете написать свой собственный "исполнитель". / thread-pool, принимающий что-то более сложное, чем Runnable [как, скажем, CancellableRunnable]).

Теперь в стандартной реализации ExecutorService, если поток каким-то образом завершается в процессе использования, он автоматически заменяется новым потоком, но это не то "повторное использование", о котором они говорят. В этом случае нет никакого "повторного использования".

Итак, верно, что вы не можете вызвать start() на Java Thread дважды но вы можете передать исполнителю столько Runnable, сколько хотите, и метод Runnable каждого run() будет вызван один раз.

Вы можете передать 30 Runnable 5 Java Thread и каждый рабочий поток может вызывать, например, run() 6 раз (практически нет гарантии, что вы будете выполнять именно 6 Runnable на Thread, но это уже детали).

В этом примере start() был бы вызван 6 раз. Каждый из этих 6 start() вызовет ровно один раз метод run() каждого Thread:

Из Thread.start() Javadoc:

 * Причина начала выполнения этого потока; виртуальная машина Java 
 * вызывает метод run этого потока.

НО затем внутри метода run() каждого потока Runnable будет декеирован и будет вызван метод run() каждого Runnable. Таким образом, каждый поток может обрабатывать несколько Runnable. Это то, что называют "повторным использованием потоков".

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

Я полагаю, что часть путаницы (а она есть) происходит из-за того, что Thread принимает Runnable и при вызове start() вызывается метод run() Runnable, а пулы потоков по умолчанию also принимают Runnable.

49
ответ дан 7 November 2019 в 08:07
поделиться

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

Дополнительные сведения см. В документации .

5
ответ дан 7 November 2019 в 08:07
поделиться

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

Отредактировано для добавления:

Вот метод run внутреннего класса Worker в ThreadPoolExecutor .

696:         /**
697:          * Main run loop
698:          */
699:         public void run() {
700:             try {
701:                 Runnable task = firstTask;
702:                 firstTask = null;
703:                 while (task != null || (task = getTask()) != null) {
704:                     runTask(task);
705:                     task = null; // unnecessary but can help GC
706:                 }
707:             } finally {
708:                 workerDone(this);
709:             }
710:         }
14
ответ дан 7 November 2019 в 08:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: