2014-01-12 3 views
2

У меня есть ThreadPoolExecutor:прерывания Runnable, который занимает несколько часов

ThreadPoolExecutor service = new ThreadPoolExecutor(N_THREADS, N_THREADS, 0L, TimeUnit.MILLISECONDS, blockingQueue, rejectedExecutionHandler); 

Служба выполняет потоки реализации Runnable интерфейс. Каждый поток обрабатывает файл на диске. Я обнаружил, что через несколько часов два потока (или ядра в зависимости от того, что показывает htop в Linux) работают и работают 13 часов. Хуже всего то, что остальные ядра не показали активности, как будто они ожидали завершения двух потоков.

Вопросы: 1 - Я много читал о том, как эта проблема может быть решена, но ничего окончательного. Насколько я могу это сделать, вы НЕ МОЖЕТЕ остановить Runnable с помощью ThreadPoolExecutor, потому что это независимый поток, который только запускается. Использование будущего рамок:

Future<?> f = f.get(submittedtask,XX) 

позволяет установить тайм-аут и принести будущий результат, но получить блоки все нити эффективно делает серийник реализации. Можно ли прерывать Runnable по истечении заданного времени с помощью threadpoolexecutor, вернуть поток в пул, чтобы он мог выполнить новую задачу и продолжить.

2 - Моя большая проблема заключается в том, почему, используя htop, я вижу два потока/ядра, и ни одно другое ядро ​​/ нить не работает, несмотря на то, что многие задачи все еще ждут выполнения (т. Е. Осталось много файлов для обработки). Любое понимание?

+0

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel%28boolean%29. Что касается количества занятых ядер: какова ценность N_THREADS? Сколько ядер у вас есть? –

+0

Прикрепите отладчик к запущенной JVM. Для этого вам нужно запустить JVM с правильными параметрами отладки. –

+0

N_Threads 24, поэтому 12 ядер (Intel Xeon E5 что-то) – user1938803

ответ

1

Вы можете создать второй запланированный пул потоков, на который вы отправите задачи отмены для каждого из возвращаемых Future. Каждая из этих задач после заданного тайм-аута проверяет, соответствует ли она Future, а если нет, отмените ее. Отмена приведет к прерыванию потока, поэтому вам может потребоваться его поддержка в ваших задачах, проверив прерванный флаг: Thread.interrupted().

Размер этого второго пула потоков может быть минимальным, то есть 1, так как это задание занимает минимум процессорного времени.

Пример кода:

ScheduledExecutorService service = Executors.newScheduledThreadPool(1); 

... 

while(...){ 
    final Future<?> f = pool.submit(...); 

    service.schedule(new Runnable() { 
     @Override 
     public void run() { 
      if(!f.isDone()){ 
       f.cancel(true); 
      } 
     } 
    }, 1, TimeUnit.MINUTES); 
} 

service.awaitTermination(1, TimeUnit.MINUTES); 
service.shutdown(); 
+0

Интересная идея. Таким образом, задания подаются в пул имен ThreadedExecutorPool, а другая служба отменяет его, если требуется слишком много времени. Мой вопрос заключается в том, насколько это обобщается для машин со многими ядрами и потоками. Мне кажется, что график должен ждать завершения конкретной работы для каждой поданной заявки. Разве это не создает шею бутылки? – user1938803

+0

Извините, я пропустил ваш вопрос. Запланированные задания помещаются в очередь и извлекаются, когда приходит время. Узким местом для «ScheduledExecutorService» является вставка/удаление, которое является «O (log n)» + временем блокировки. Я не думаю, что это создаст какие-либо проблемы в большинстве ситуаций, хотя лучше всего это измерить его для вашего дела. –

+0

Да, это была моя забота, но если удаление вставки происходит быстро, то, как вы говорите, я также сомневаюсь, что это вызовет проблемы. Большое спасибо за помощь! – user1938803

0

Вы можете сказать что-нить вы желание к interrupt:

Прерывание является указание в теме, что он должен прекратить то, что это делать и делать что-то еще.

Вы можете прервать свою нить с помощью Future.cancel(true). Вы несете ответственность за внедрение Runnable таким образом, чтобы он выполнял это желание, проверяя его состояние Thread.interrupted().

0

Для получения более подробной информации о процессе резьбы запуска:

ps -eLf | grep <PROCESS_PID> 

Поскольку HTOP показывает список запущенных процессов, где каждый процесс имеет по меньшей мере одну нить.

Смежные вопросы