Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Итак, правда, вы не можете дважды называть start() в Java-потоке, но вы можете передать столько Runnable, сколько хотите исполнителю, и каждый метод Runnable run() должен вызываться один раз.

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

В этом примере start() можно было бы назвать 6 раз. Каждый из этих 6 start() будет вызывать ровно один раз метод 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() Runnable, удалите следующий Runnable (или блок) и запустите его метод run(), затем промойте и повторите.

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

Ответ 2

Метод потоков 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:         }

Ответ 3

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

Подробнее см. .

Ответ 4

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

Ответ 5

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

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