ScheduledThreadPoolExecutor и corePoolSize 0?
Я хотел бы иметь ScheduledThreadPoolExecutor
, который также останавливает последний поток, если нет работы, и создает (и сохраняет потоки в течение некоторого времени), если есть новые задачи. Но как только больше нет работы, он должен снова отбросить все потоки.
Я наивно создал его как new ScheduledThreadPoolExecutor(0)
, но, как следствие, ни один нить никогда не создавался, и никакая запланированная задача никогда не выполнялась.
Может ли кто-нибудь сказать мне, могу ли я достичь своей цели, не написав свою собственную обертку вокруг ScheduledThreadPoolExecutor
?
Спасибо заранее!
Ответы
Ответ 1
На самом деле вы можете это сделать, но его неочевидное:
- Создайте новый ScheduledThreadPoolExecutor
- В конструкторе установите основные потоки в максимальное количество потоков, которые вы хотите
- установить keepAliveTime исполнителя
-
и, наконец, разрешить тайм-ауту основных потоков
m_Executor = new ScheduledThreadPoolExecutor ( 16,null );
m_Executor.setKeepAliveTime ( 5, TimeUnit.SECONDS );
m_Executor.allowCoreThreadTimeOut ( true );
Это работает только с Java 6, хотя
Ответ 2
Чтение ThreadPoolExecutor javadocs может предполагать, что решение Alex V в порядке. Однако это приведет к ненужному созданию и уничтожению потоков, не что иное, как обналиченный пул потоков. ScheduledThreadPool не предназначен для работы с переменным числом потоков. Посмотрев на источник, я уверен, что вы в конечном итоге создадите новый поток почти каждый раз, когда вы отправляете задание. Решение Joe должно работать, даже если вы ТОЛЬКО отправляете отложенные задачи.
PS. Я бы отслеживал ваши потоки, чтобы убедиться, что вы не тратите ресурсы в своей текущей реализации.
Ответ 3
Я подозреваю, что ничего из java.util.concurrent
не сделает это за вас, просто потому, что если вам нужна служба расписания, то у вас часто возникают повторяющиеся задачи. Если у вас есть повторяющаяся задача, тогда обычно имеет смысл просто поддерживать один и тот же поток и использовать его для следующего повторения задачи, вместо того, чтобы срывать ваш поток и создавать новый при следующем повторении.
Конечно, запланированный исполнитель может быть использован для вставки задержек между нерегулярными задачами или может использоваться в тех случаях, когда ресурсы настолько скудны, и повторение настолько редко, что имеет смысл срывать все ваши потоки до тех пор, пока новый работа приходит. Итак, я вижу случаи, когда ваше предложение определенно имеет смысл.
Чтобы реализовать это, я хотел бы попытаться обернуть пул кэшированных потоков из Executors.newCachedThreadPool
вместе с однопоточной запланированной службой-исполнителем (т.е. new ScheduledThreadPoolExecutor(1)
). Задачи могут быть запланированы через запланированную службу-исполнитель, но запланированные задачи будут завернуты таким образом, что вместо того, чтобы выполнить однопотоковый запланированный исполнитель, однопоточный исполнитель передаст их в пул кэшированных потоков для фактических выполнение.
Этот компромисс даст вам максимум одного потока, когда нет абсолютно никакой работы, и это даст вам столько потоков, сколько вам нужно (в пределах вашей системы, конечно), когда есть много работать.
Ответ 4
Эта проблема является известной ошибкой в ScheduledThreadPoolExecutor (Идентификатор ошибки 7091003) и исправлена в Java 7u4. Хотя глядя на патч, исправление заключается в том, что "по крайней мере один поток запущен, даже если corePoolSize равен 0".