ScheduledThreadPoolExecutor и corePoolSize 0? - PullRequest
15 голосов
/ 25 февраля 2010

Я хотел бы иметь ScheduledThreadPoolExecutor, который также останавливает последний поток, если нет работы, и создает (и поддерживает потоки в течение некоторого времени), если есть новые задачи. Но когда больше не нужно ничего делать, он должен снова отбросить все потоки.

Я наивно создал его как new ScheduledThreadPoolExecutor(0), но, как следствие, ни один поток не создается, и никакие запланированные задачи никогда не выполняются.

Кто-нибудь может мне сказать, смогу ли я достичь своей цели, не написав свою собственную обертку вокруг ScheduledThreadpoolExecutor?

Заранее спасибо!

Ответы [ 4 ]

14 голосов
/ 22 июля 2010

На самом деле вы можете сделать это, но это неочевидно:

  • Создать новый ScheduledThreadPoolExecutor
  • В конструкторе установите для основных потоков максимальное количество потоков, которое вы хотите
  • установить keepAliveTime исполнителя
  • и, наконец, разрешить тайм-аутам основных потоков

    m_Executor = new ScheduledThreadPoolExecutor ( 16,null );
    m_Executor.setKeepAliveTime ( 5, TimeUnit.SECONDS );
    m_Executor.allowCoreThreadTimeOut ( true );
    

    Это работает только с Java 6, хотя

8 голосов
/ 05 декабря 2010

Чтение javadocs ThreadPoolExecutor может указывать на правильность решения Alex V. Тем не менее, это приведет к ненужному созданию и уничтожению потоков, ничего подобного обналиченному пулу потоков. ScheduledThreadPool не предназначен для работы с переменным числом потоков. Посмотрев на источник, я уверен, что вы будете создавать новый поток почти каждый раз, когда отправляете задачу. Решение Джо должно работать, даже если вы отправляете ТОЛЬКО отложенные задачи.

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

7 голосов
/ 25 февраля 2010

Я подозреваю, что ничто из java.util.concurrent не сделает это за вас, просто потому, что если вам нужна служба выполнения по расписанию, то вам часто приходится выполнять повторяющиеся задачи. Если у вас есть повторяющаяся задача, то обычно имеет больше смысла, чтобы просто сохранить тот же поток и использовать его для следующего повторения задачи, а не разрывать поток и создавать новый. при следующем повторении.

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

Чтобы реализовать это, я рассмотрел бы попытку обернуть кэшированный пул потоков из Executors.newCachedThreadPool вместе с однопоточным сервисом запланированного выполнения (т. Е. new ScheduledThreadPoolExecutor(1)). Задачи могут быть запланированы через службу запланированного исполнителя, но запланированные задачи будут упакованы таким образом, что вместо того, чтобы ваш однопоточный запланированный исполнитель выполнял их, однопоточный исполнитель передал бы их в пул кэшированных потоков для фактического выполнение.

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

5 голосов
/ 05 августа 2012

Эта проблема является известной ошибкой в ​​ScheduledThreadPoolExecutor ( Идентификатор ошибки 7091003 ) и исправлена ​​в Java 7u4. Хотя смотрит на патч , исправление состоит в том, что «хотя бы один поток запущен, даже если corePoolSize равен 0».

...