Желание, которое вы выражаете, напоминает мне о бутылке Кляйна , где мало что различается между тем, что «внутри» и «снаружи».Здесь задачи, отправленные на ExecutorService
, должны знать, что они должны уведомить защелкивающиеся ворота за пределами пула потоков и закрыть его при первом переходе от невидимых истинных результатов задачи к просмотру хотя бы одного.
Я не буду писать код для вас, но я нарисую решение.Это может помочь определить интерфейс, по которому задачи должны вызываться при завершении:
interface TaskObserver
{
void completed(boolean result);
}
Каждый экземпляр задачи может быть создан со ссылкой на такой TaskObserver
, для которого тело задачи будет вызывать толькодо его завершения и возвращает управление обратно вызывающему ExecutorService
.Вы могли бы даже написать базовый класс, чтобы помочь в участии в этом протоколе:
public abstract class ObservableTask implements Callable<Boolean>
{
protected ObservableTask(TaskObserver observer)
{
if (null == observer)
throw NullPointerException();
observer_ = observer;
}
public final Boolean call()
{
final boolean result = evaluate();
observer_.completed(result);
return result;
}
protected abstract boolean evaluate();
private final TaskObserver observer_;
}
В качестве альтернативы, вместо использования расширения для определения задач, вы можете написать конкретный класс, подобный этому, который принимает ссылку в Callable<Boolean>
в своем конструкторе в дополнение к ссылке TaskObserver
и работает через делегирование.
В дальнейшем реализация TaskObserver
будет хранить AtomicBoolean
, который должен быть изначально установлен в значение false.Тело метода completed(boolean)
должно пытаться установить AtomicBoolean
из false в true, если результат, переданный в completed(boolean)
, равен true.Если переход от ложного к истинному завершился успешно, выключите ExecutorService
и прекратите отправлять больше задач;любые последующие вызовы на номер TaskObserver
будут поступать из задач, которые уже были отправлены и были слишком далеко, чтобы удовлетворить запрос на отмену.
public void complete(boolean result)
{
if (result &&
latch_.compareAndSet(false, true))
{
// Set a flag to cease submitting new tasks.
service_.shutdownNow();
if (!service_.awaitTermination(timeoutMagnitude, timeoutUnit))
{
// Report a problem in shutting down the pool in a timely manner.
}
}
}
Если этого недостаточно, чтобы начать работуПожалуйста, ответьте на дополнительные вопросы.