ThreadPoolExecutor - ArrayBlockingQueue ... ждать, пока он не удалит элемент из очереди - PullRequest
1 голос
/ 05 октября 2010

Я пытаюсь настроить поток, который выполняет следующее:

Пул потоков только с 1 потоком [CorePoolSize =0, maxPoolSize = 1]

Используется очередь ArrayBlockingQueue

Quesize = 20

BackGround:
Поток пытается прочитать запрос и выполнить над ним операцию.

ОДНАКО, со временем количество запросов увеличилось настолько, что поток всегда занят и потребляет 1 ЦП, что делает его ресурсом.

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

То, что мне нужно было бы сделать, это перевести режим сна в режим «операция», чтобы для каждой задачи поток некоторое время спал и высвобождал процессор.

Quesiton:
Однако мне было интересно, есть ли способ использовать очередь, которая в основном сама спит какое-то время, прежде чем читает следующий элемент. Это было бы идеально, так как выполнение задачи в середине выполнения и сохранение ее незавершенным просто не звучит лучше для меня.

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

Спасибо.

Edit: Я добавил дополнительный вопрос здесь исправил размер maxpool до 1 [записано в спешке]. Спасибо, Тим, за то, что указал на него.

Ответы [ 4 ]

1 голос
/ 07 октября 2010

Причина, по которой поток потребляет 100% ресурсов ЦП, заключается в том, что ему дается больше работы, чем он может обработать. Добавление задержки между задачами не решит эту проблему. Это только усугубляет ситуацию.

Вместо этого вы должны посмотреть, ПОЧЕМУ ваши задачи потребляют так много ресурсов процессора, например с профилировщиком и измените их так, чтобы они потребляли меньше ресурсов ЦП, пока не обнаружите, что ваш поток может не отставать и он больше не потребляет 100% процессорного времени.

1 голос
/ 05 октября 2010

Вы можете создать подкласс ThreadPool и переопределить beforeExecute на некоторое время для сна:

@Overrides
protected void beforeExecute(Thread t,
                         Runnable r){
    try{
       Thread.sleep( millis);  // will sleep the correct thread, see JavaDoc
    }
    catch (InterruptedException e){}

  }

Но см. Комментарий AngerClown о искусственном замедлении очереди, вероятно, не очень хорошая идея.

1 голос
/ 06 октября 2010

Это может не сработать, но вы можете попытаться установить низкий приоритет потока исполнителя.

По существу, создайте ThreadPoolExecutor с пользовательской ThreadFactory .Пусть метод ThreadFactory.newThread() возвращает Threads с приоритетом Thread.MIN_PRIORITY .Это приведет к тому, что используемая вами служба исполнителя будет запланирована только при наличии доступного ядра для ее запуска.

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

1 голос
/ 05 октября 2010

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

Пауза в задаче в очереди - единственный способ заставить поток бездействовать, несмотря на задачи в очереди. Теперь «сон» не обязательно должен быть в той же задаче, что и «работа» - вы можете ставить в очередь отдельную задачу отдыха после каждой реальной задачи, что может обеспечить более чистую реализацию. Что еще более важно, если работа представляет собой Callable, который возвращает результат, разделение на две задачи позволит вам получить результат как можно скорее.

В качестве уточнения, вместо того, чтобы спать в течение фиксированного интервала между каждой задачей, вы можете «дросселировать» выполнение до заданной скорости. Это позволит вам избежать ненужного ожидания между задачами, но при этом избежать выполнения слишком большого количества задач в течение определенного промежутка времени. Вы можете прочитать другой мой ответ для простого способа реализовать это с помощью DelayQueue.

...