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

Я создаю консольный решатель судоку, основной целью которого является скорость.

Теперь у меня есть ManagerThread, который запускает WorkerThreads для вычисления соседей каждой ячейки. Итак, прямо сейчас для каждой ячейки запускается один WorkerThread. Как я могу повторно использовать существующий поток, который завершил свою работу?

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

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

Спасибо


person David    schedule 06.06.2010    source источник
comment
Дополнительные исследования о том, как это работает: stackoverflow.com/questions/2324030/java-thread-reuse - переполнение стека   -  person Eddy    schedule 04.02.2017


Ответы (4)


Взгляните на предоставленный Java SE java.util.concurrent API. Вы можете создать пул потоков, используя Executors#newFixedThreadPool(), и вы можете отправлять задачи, используя ExecutorService методы. Не нужно изобретать собственный пул потоков. Также см. руководство Sun по этому вопросу.

person BalusC    schedule 06.06.2010
comment
@David: Имейте в виду, что для чисто вычислительных задач наличие большего количества потоков, чем доступных ядер, скорее замедлит, чем ускорит ваш код. Очевидно, что это меняется, если у вас есть блокировка потока при вводе-выводе или что-то в этом роде. - person T.J. Crowder; 06.06.2010
comment
@Т.Дж. имеет справедливую точку зрения. @David, проверьте Runtime#availableProcessors()< /а>. - person BalusC; 06.06.2010
comment
@BalusC: спасибо, похоже, то, что мне нужно. @TJ: правда? Создание нескольких потоков с высоким значением приоритета не будет отвлекать больше ресурсов ЦП от других уже запущенных процессов с более низким приоритетом? - person David; 09.06.2010
comment
@David: Не за что. Не забудьте отметить принятый ответ (щелкните зеленую галочку, см. также stackoverflow.com/faq). И да, большее количество потоков, чем доступных ядер, приведет к увеличению накладных расходов на их управление, что, в конце концов, может быть медленнее. - person BalusC; 09.06.2010
comment
@BalusC: я только что пометил это как принятое ... сессия cookie не позволила мне это сделать, но теперь это исправлено! ;-) - person David; 10.06.2010

при использовании пула потоков (java.util.concurrent) вы фактически никогда не инициализируете поток, а скорее передаете Runnables в пул потоков. вам не нужно беспокоиться о жизненном цикле потока, просто выполняйте любую работу, которую вам нужно выполнить, в runnable и дайте ей выйти, когда она будет выполнена.

person Omry Yadan    schedule 06.06.2010

Изучите использование синхронизации CyclicBarrier: http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html

person Chris Dennett    schedule 06.06.2010

Что ж, если бы мне пришлось кодировать эту логику самостоятельно, а не использовать такой пакет, как Quartz от OpenSymphony, я бы сделал следующее: у меня был бы WorkerThread, который расширяет Thread. Этот класс также будет иметь частное свойство runnable, которое называется Runnable. Это свойство будет содержать ссылку на код, который вы хотите выполнить. Имейте общедоступный сеттер для этого. Код основного потока начнется с запуска исполняемого объекта, которым вы его инициализировали, а затем переключится в состояние ожидания. Перед этим он отметит менеджеру пула, что он завершен, и его можно вернуть в пул. В следующий раз, когда вам понадобится поток, вы выбираете его из пула, вызываете setRunnable, который устанавливает свойство runnable, а затем пробуждаете поток. Он вернется к работе, войдет в бесконечный цикл: выполнить и запустить и вернуться в состояние ожидания.

person Community    schedule 06.06.2010