wait()
является операцией блокировки:
Заставляет текущий поток ждать, пока другой поток не вызовет метод notify () или notifyAll ()
Это означает, что поток в пуле будет ожидать, но снаружи он просто выглядит так, как будто текущая задача занимает так много времени. Это также означает, что если выполнено 5 задач и все они wait()
, Executor
не сможет обработать оставшиеся задачи, которые, например, ждут в очереди.
Правда, сам поток-исполнитель переходит в спящий режим, позволяя другим потокам переключаться и использовать ЦП (поэтому вы можете одновременно ожидать сотни потоков, и ваша система все еще реагирует), но поток все еще "непригоден" и заблокирован .
Еще одна интересная функция - прерывание - если поток чего-то ждет или спит, вы можете прервать его. Обратите внимание, что wait()
и Thread.sleep()
объявляют InterruptedException
. С ExecutorService
вы можете воспользоваться этим, просто вызвав: future.cancel()
(future
- это объект, который вы получили взамен при отправке задачи в ExecutorService
).
Наконец, я думаю, вам следует изменить свое решение. Вместо активного ожидания завершения работы внешней системы предоставьте API с обратными вызовами:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItsDone(new Callback() {
public void done() {
doSomethingElse();
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
Таким образом, API внешней системы просто уведомит вас, когда будут готовы результаты, и вам не придется ждать и блокировать ExecutorService
. Наконец, если doSomethingElse()
отнимает много времени, вы можете даже решить запланировать его, а не использовать сторонний поток ввода-вывода:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItIsDone(new Callback() {
public void done() {
pool.submit(new Callbale<Void>() {
public Void call() {
doSomethingElse();
}
}
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
ОБНОВЛЕНИЕ: вы спрашиваете, что делать с таймаутами? Вот моя идея:
pool.execute(new Runnable(){
try{
doSomethingAndCallMeBackWhenItsDone(new Callback() {
public void done() {
doSomethingElse();
}
public void timeout() {
//opps!
}
});
}catch(Exception e){ throw new RunTimeException(e) }
});
Я полагаю, вы можете реализовать тайм-аут на стороне третьей стороны, и если там происходит тайм-аут, просто вызовите метод timeout()
.