为共享计算实现Future接口

时间:2015-09-29 10:21:48

标签: java multithreading future

我实现了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()

事情是,这样的解决方案对我来说似乎有点奇怪...不确定。

1 个答案:

答案 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>的状态,并根据需要返回或抛出。