2013-06-01 2 views
4

В моем коде есть пул потоков, реализованный с фиксированным пулом потоков ExecutorService. Большинство задач, выполняемых пулом, очень короткие, но порой есть одна задача, которая будет работать в течение длительного времени, около 20-30 секунд. При выполнении этой задачи новые задачи не выполняются и будут возобновляться только при завершении заданий, выполняемых в течение длительного времени.Фиксированный пул ExecutorService зависает по одной задаче

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

Я задумался, почему он застрял, а затем переключился с newFixedThreadPool() на newCachedThreadPool(), и узкое место было выпущено. Это единственное изменение, которое я сделал.

Имеет ли смысл такое поведение? Код, кажется, работает нормально, поэтому, я думаю, я сохраню изменения, и насколько я понимаю, лучше использовать пул потоков кеша, если у вас много коротких задач, но мне было интересно, почему фиксированный пул зависает и есть способ исправить это?

Кроме того, что может быть связано с проблемой, если она есть, для переключения с фиксированного на кеш?

Спасибо.

+0

Кажется, не имеет смысла. Вы уверены, что ничего не изменили? – Thilo

+2

Когда проблема появляется снова, сделайте 'kill -QUIT', чтобы получить трассировки стека всех потоков, чтобы увидеть, что они делают. – Thilo

+3

Все зависит от того, как вы создали свой пул потоков. Покажите нам код, и мы можем найти причину. –

ответ

0

Возможный результат: больше потоков будет запущено в то же время, потому что newCachedThreadPool() позволяют запускать подсчет целых целых.MAX_VALUE.

Трудно угадать влияние стороны, не просматривая ваш код.

Но, как я думаю, если проблема решена путем увеличения количества потоков, есть большой шанс, что у вас есть блокировки.

Например, вы имеете 4 ресурсов A, B, C, D. и 4 задачи:

1) короткая Таска требует ресурсов A
2) короткий TaskB требует ресурс B
3) короткие TaskC требуют ресурс C
4) длиной TaskD требуют ресурсов а и D

Таким образом, в один момент времени мы будем иметь следующую ситуацию:

Thread1: TaskA await for resource A 
Thread2: TaskD has A and D and running 

TaskB wait in Queue 
TaskC wait in Queue 

При изменении тянуть тянуть с неограниченным кол-нить, или фиксированный пул потоков с большим количеством разрешенных нитей:

Thread1: TaskA await for resource A 
Thread2: TaskD has A and D and running 
Thread3: TaskB has resource B 
Thread4: TaskC has resource C 

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