我实现了Future<Collection<Integer>>
接口,以便在应用程序中的所有线程之间共享一些批量计算的结果。
实际上,我打算只将一个实现Future<Collection<Integer>>
的类的实例放到ApplicationScope对象中,这样任何需要结果的其他线程只需要Future
中的object
。并在其上调用方法get()
,因此使用由另一个线程执行的计算。
我的问题是关于实施cancel
方法。现在,我会这样写:
public class CustomerFutureImpl implements Future<Collection<Integer>>{
private Thread computationThread;
private boolean started;
private boolean cancelled;
private Collection<Integer> computationResult;
private boolean cancel(boolean mayInterruptIfRunning){
if( computationResult != null )
return false;
if( !started ){
cancelled = true;
return true;
} else {
if(mayInterruptIfRunning)
computationThread.interrupt();
}
}
//The rest of the methods
}
但是方法实现并不满足Future的文档,因为我们需要在等待结果的任何线程中抛出CancellationException
(已调用get()
方法)
我应该添加另一个字段,如private Collection<Thread> waitingForTheResultThreads;
,然后从Collection
中断每个线程,捕获中断的异常,然后throw new CancellationException()
?
事情是,这样的解决方案对我来说似乎有点奇怪...不确定。
答案 0 :(得分:2)
通常,您应该避免直接实施Future
。并发代码非常难以正确使用,分布式执行的框架 - 尤其是ExecutorService
- 将提供引用您关注的工作单元的Future
个实例。
您可能已经知道并且正在有意创建一个新的类似服务,但我觉得重要的是要说明对于浩大的大多数用例,您不需要定义自己的{ {1}}实施。
您可能希望查看Guava提供的并发工具,特别是ListenableFuture
,它是Future
的子接口,提供其他功能。
假设您确实想要定义自定义Future
类型,请使用Guava的AbstractFuture
实现作为起点,这样您就不必重新发明您遇到的复杂细节
对于您的具体问题,如果您查看implementation of AbstractFuture.get()
,您会看到它是通过Future
循环实现的,该循环会查找while
变为非空,它调用value
的时间,它返回值或引发getDoneValue()
。基本上,每次调用CancellationException
时阻止的每个帖子都会频繁地轮询Future.get()
字段,并在检测到Future.value
被取消时提出CancellationException
。没有必要跟踪Future
或类似的任何事情,因为每个线程可以独立地检查Collection<Thread>
的状态,并根据需要返回或抛出。