Потоки исполнителей не завершаются

Я использую метод Executors.newFixedThreadPool(100). Для выполнения одной команды требуется около 20 потоков. После выполнения команды 5-6 раз приложение перестает отвечать. Мой поток реализует Callable.

Я сомневаюсь, что этот поток не завершается после завершения. Я также вызвал shutdown(), чтобы завершить поток.

Может ли кто-нибудь сказать, когда я использую метод get() для получения результата потока, завершается ли он (то есть удаляется из очереди) или он все еще находится в очереди, которая используется пулом для хранения потоков.


person Raman    schedule 06.06.2011    source источник


Ответы (4)


Потоки не завершаются. Что происходит, так это:

  • Все рабочие потоки ждут входной очереди
  • Один поток извлекает элемент head из очереди
  • Он запускает Callable
  • Он помещает результат в очередь результатов
  • Ожидает новый элемент во входной очереди

Таким образом, либо очередь результатов переполняется, либо ваш Callable не возвращается.

person Aaron Digulla    schedule 06.06.2011

get() — это блокирующий вызов. Это означает, что вызывающий поток останавливается до тех пор, пока работающий поток не завершит свою задачу и не будет доступен результат.

Исполнитель позаботится о том, чтобы взять задачи из очереди и очистить их, поэтому ответ «нет» — это не «все еще в очереди».

Осторожно, используйте 100 потоков — это смехотворно большое число. Попробуйте от 2 до 8 для типичной машины (все зависит от того, сколько времени тратится на ожидание других вещей, например, ввода-вывода - чем больше ваши задачи связаны с процессором, тем меньше потоков вы должны использовать.

person Bohemian♦    schedule 06.06.2011

  1. Даже после вызова get() поток все равно будет находиться в очереди. На самом деле API гарантирует, что даже если поток умирает, он воссоздает его для поддержания «фиксированности» (фиксированное количество потоков в вашем пуле).

  2. Обратите внимание, что если потоки в вашем пуле действительно выполняют какую-то задачу (кроме ожидания), вызов shutdown не завершит поток. Так, например. если ваши потоки находятся в бесконечном цикле, что-то делая, то вызов выключения бесполезен.

person Suraj Chandran    schedule 06.06.2011
comment
Спасибо за ответ. Меня больше беспокоило, когда я вызываю get() и получаю результат этого вызова, удаляется ли поток из очереди или он все еще занимает место в очереди. - person Raman; 06.06.2011

Вызов shutdown() только останавливает пул потоков от принятия новых задач и позволяет завершить все потоки после выполнения всех задач.

Сколько у вас ядер? Если у вас есть 100 занятых потоков и, скажем, 4 ядра, каждый поток получит лишь небольшое количество процессорного времени.

person Peter Lawrey    schedule 06.06.2011