Как избежать взаимных блокировок и использования слишком большого количества потоков? - PullRequest
4 голосов
/ 14 апреля 2011

Использование Executors.newFixedThreadPool(int nThreads) - это хороший способ минимизировать накладные расходы на создание слишком большого количества потоков, но это может привести к тупику в случае, если все потоки ожидают другого задания, которое само ожидает освобождения потока из пула. Иногда проблему можно решить, используя несколько пулов потоков, но иногда это невозможно. Я ищу что-то похожее на newFixedThreadPool, за исключением случая, когда все потоки пула заблокированы - в таком случае пул должен расти, несмотря на свою предопределенную границу. Есть ли что-то подобное?


На самом деле тупик здесь не так важен. Реальная проблема заключается в том, «как управлять количеством запущенных потоков», а не их общим количеством. Это также может быть интересно, когда вы пытаетесь полностью использовать процессор, не создавая ненужных потоков.

Ответы [ 3 ]

4 голосов
/ 14 апреля 2011

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

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

2 голосов
/ 31 октября 2011

Обычно плохой идеей является блокировка потоков в пуле в ожидании других потоков в том же пуле потоков.

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

В качестве альтернативы вы можете делать то, что Swing делает с модальными диалоговыми окнами, и иметь поток, который собирается блокировать запуск дочернего потока, чтобы продолжать обрабатывать запросы, пока родительский поток не разблокируется. Это сложно сделать правильно, и вам потребуется вручную управлять потоками, что намного менее безопасно, чем при использовании Executor.

1 голос
/ 14 апреля 2011

Executor.newCachedThreadPool(); Кэшированный пул потоков проверит наличие доступных потоков.Если есть, пул потоков будет повторно использовать поток.Если это не так, пул потоков создаст новый поток.Время жизни потоков составляет 60 секунд, поэтому через 60 секунд дополнительные потоки будут прерваны.

...