2010-11-13 5 views
0

Я пытался запустить ExecutorService объект с FixedThreadPool, и я столкнулся с проблемами.Исполнитель java

Я ожидал, что программа будет работать в наносекундах, но она была повешена. Я обнаружил, что мне нужно использовать Semaphore вместе с ним, чтобы элементы в очереди не складывались.

Есть ли способ узнать, что используются все потоки пула.

Базовый код ...

static ExecutorService pool = Executors.newFixedThreadPool(4); 
static Semaphore permits = new Semaphore(4); 
try { 
    permits.acquire(); 
    pool.execute(p); // Assuming p is runnable on large number of objects 
    permits.release(); 
} catch (InterruptedException ex) { 
} 

Этот код получает повешен, и я действительно не знаю, почему. Как узнать, ожидает ли пул в ожидании завершения всех потоков?

ответ

3

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

В блоге, на который вы ссылаетесь в своем комментарии, используется семафор, чтобы ограничить объем работы, который может быть поставлен в очередь сразу, что не будет проблемой для вас, пока у вас не будет много тысяч задач в очереди, и они начнут есть в доступная память. Есть более простой способ сделать это, в любом случае - построить ThreadPoolExecutor с ограниченной очередью. * Но это не ваша проблема.

Если вы хотите знать, когда завершает задачу, обратите внимание, что ExecutorService.submit() возвращает Future объект, который может быть использован, чтобы ждать завершения данных задачи:

Future<?> f = pool.execute(p); 
f.get(); 
System.out.println("task complete"); 

Если у вас есть несколько задач, и хотите ждать все они должны заполнить, либо сохранить каждый Future в списке, а затем позвонить по номеру get() по очереди или исследовать ExecutorService.invokeAll() (что по сути делает то же самое, но в одном вызове метода).

Вы также можете сказать, имеет ли задача завершена или нет:

Future<?> f = pool.execute(p); 

while(!f.isDone()) { 
    // do something else, task not complete 
} 

f.get(); 

Наконец, следует отметить, что даже если ваши задачи будут выполнены, ваша программа не может выйти (и, таким образом, по-видимому, «зависание»), если вы не вызвали shutdown() в пуле потоков; причина в том, что потоки все еще работают, ожидая, что им будет больше работы.

* Edit: извините, я просто перечитайте мой ответ и понял, что эта часть неверно - ThreadPoolExecutorпредлагает задачи в очереди и отвергает их, если они не будут приняты, поэтому ограниченная очередь имеет различную семантику к семафорному подходу.

1

Вам не нужен Семафор.

Если вы висели, это, вероятно, потому, что нити запираются в другом месте.

Запустите код в Debuger и, когда он зависает, приостановите его и посмотрите, что делают потоки.

+0

Я думаю, что семафор существует, потому что нет другого способа блокировать, если все 4 потока заняты - исполнитель будет генерировать исключение, тогда как нам нужно его заблокировать подающий поток. – skaffman

+1

Какие исключения вы видите, будучи брошенными? Новые задачи, которые вы отправляете, должны быть просто поставлены в очередь Исполнителем, если все потоки заняты. – nos

+0

Эй, я прочитал этот блог и предположил, что мне нужно сделать ssemaphores. http://blog.readpath.com/2010/01/20/java-fixedthreadpool/ – 2010-11-13 20:26:21

0

Вы можете перейти по ссылке ThreadPoolExecutor. Он содержит метод getActiveCount(), который возвращает приблизительно количество активных потоков. Почему он приблизительный, я не уверен.

+0

Счет может стать недействительным, если поток завершит выполнение во время вычисления 'getActiveCount()' или непосредственно перед тем, как он вернет ответ вызывающему абоненту. – SimonJ

+0

Не могу ли я узнать, что служба-исполнитель в настоящее время заблокирована? Я имею в виду, что должен быть способ, чтобы другие потоки переходили в спящий режим до тех пор, пока используемые не будут работать ....... – 2010-11-13 20:34:15

+0

@SimonJ Хорошая точка. –

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