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


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

Я вижу в док Executors класс:

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

запомните слово "повторное использование".

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

5   51   2010-02-24 09:06:11

5 ответов:

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

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

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

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

так это правда, что вы не можете позвонить start() на какой-нить Яве два раза но вы можете пройти столько Runnable Как вы хотите, чтобы исполнитель и каждый Runnable ' s run() метод должен быть вызван один раз.

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

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

С Thread.start() Javadoc:

 * Causes this thread to begin execution; the Java Virtual Machine 
 * calls the <code>run</code> method of this thread.

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

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

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

The 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:         }

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

посмотреть документация для более подробной информации.

пул потоков создает свои собственные потоки и предоставляет свои собственные умные маленькие Runnables для этих потоков. Эти Runnables никогда не заканчиваются, но синхронизируются в очереди (они ждут ()), пока вызываемый объект не будет присутствовать в этой очереди; они уведомляются, когда это происходит, и их Runnable запускает вызываемый объект из очереди, и весь сценарий повторяется снова.

Если thread закончено, конечно, можно использовать его снова. Вы можете убедиться, что он не работает, позвонив isAlive() или что-то подобное.

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