Исполнитель в Java - PullRequest
       2

Исполнитель в Java

0 голосов
/ 13 ноября 2010

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

Я ожидал, что программа будет работать в наносекундах, но она зависла.Я обнаружил, что мне нужно использовать 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 ]

3 голосов
/ 14 ноября 2010

По умолчанию, если вы отправляете более 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() в пуле потоков;причина в том, что потоки все еще работают, ожидая выполнения дополнительной работы.

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

1 голос
/ 13 ноября 2010

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

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

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

0 голосов
/ 13 ноября 2010

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

...