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".