如何区分Java Futures?

时间:2014-04-15 22:48:29

标签: java concurrency java.util.concurrent

似乎我应该能够在不必维护两个HashMaps(或一个双向哈希)的情况下告诉Futures彼此分开。

  1. 将作业提交给ExecutorService时,将会知道未来。使用键'jobID'添加Future以映射。
  2. 如果需要取消工作,请在地图中使用'jobID'来检索Future并取消。
  3. 如果作业成功完成,则可以通过返回的Object(包含作业ID)来标识Future。通过'jobID'从地图中删除未来。
  4. 如果作业被中断或抛出异常,则不返回Object,因此Future必须通过调用Future.hashCode或Future.equals与'jobID'匹配(因此,两个HashMaps或一个双向第三方哈希)。
  5. 我在这里遗漏了什么,或者是预期的方法?我想覆盖Future以包含'getId'方法或其他东西,但根据执行程序如何创建它们似乎不可行。

    编辑:我也在尝试使用ExecutorCompletionService来等待作业完成。

2 个答案:

答案 0 :(得分:2)

永远不要使用java.util.concurrent.Future。请改用com.google.common.util.concurrent.ListenableFuture或类似名称。 使用ListenableFuture,您可以在ListenableFuture完成时注册回调:

ListenableFuture<Integer> future = MoreExecutors.listeningDecorator(executor).submit(
  new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
      ...
    }
});

// Add jobId to the map. You should use a thread-safe Map!
map.put(jobId, future);

Futures.addCallback(future, new FutureCallback<Integer>(){
  @Override
  public void onSuccess(Integer result) {
    map.remove(jobId);
    ...
  }

  @Override
  public void onFailure(Throwable t) {
    map.remove(jobId);
    ...
  }});

答案 1 :(得分:0)

解决此问题的一种方法(我之前使用过)是创建HashMap,其中String为关键字,Map.Entry为值。您可以自己轻松实现Map.Entry界面,但基本上它提供了一个元组结构,您可以使用它来存储Future及其关联的hashCode

这样做的好处是,它可以在Future任务开始后更好地控制你的Future任务的命运(我认为这是你正在做的事情?)。不过,这有点麻烦。只需存储相关HashMap个对象的ID,即可处理成功任务和手动取消任务的情况。

此解决方案实际上只增加了处理无法正确执行的任务的能力 - 在这种情况下,假设您希望完成的潜在任务的数量是合理的,您可能最好只是处理异常,因为它们出现和维护单个Map.Entry之前的任务(无论退出状态如何)。

有关{{1}}界面的更多信息,请参阅Javadoc