我正在使用ExecutorService来处理数千个小型独立任务。每个任务在完成时都会存储结果(要么是真,要么是假(。
因此,如果任务找到了答案,我想过早地关闭线程池,而不是处理所有任务!感觉我在这里错过了一些非常明显的东西......
考虑使用 invokeAny
方法。 当只有一个完成时,它会返回。
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html#invokeAny(java.util.Collection(
你表达的愿望让我想起了一个克莱因瓶,其中"内部"和"外部"之间几乎没有区别。在这里,提交给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_;
}
或者,您可以编写一个这样的具体类,而不是使用扩展来定义任务,该类除了接受TaskObserver
引用之外,还接受对其构造函数中Callable<Boolean>
的引用,并通过委托工作。
继续,TaskObserver
的实现将存储一个AtomicBoolean
,最初必须将其设置为 false。如果传递给 completed(boolean)
的结果为 true,则 completed(boolean)
方法的主体必须尝试将AtomicBoolean
从 false 设置为 true。如果从 false 到 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.
}
}
}
如果这还不足以让您入门,请跟进其他问题。