首页 文章

如何区分Java Futures?

提问于
浏览
2

看起来我应该能够在不必维护两个HashMaps(或一个双向哈希)的情况下将Futures分开 .

  • 将作业提交到ExecutorService时已知未来 . 使用键'jobID'添加Future以映射 .

  • 如果需要取消作业,请在 Map 中使用'jobID'来检索Future并取消 .

  • 如果作业成功完成,则可以通过返回的Object(包含作业ID)来标识Future . 通过'jobID'从 Map 中删除Future .

  • 如果作业被中断或抛出异常,则不返回任何Object,因此Future必须与'jobID'通过对Future.hashCode或Future.equals的调用匹配(因此,两个HashMaps或一个双向第三方散列) .

我在这里遗漏了什么,或者是预期的方法?我想覆盖Future以包含'getId'方法或其他东西,但根据执行程序如何创建它们似乎不可行 .

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

2 回答

  • 0

    切勿使用 java.util.concurrent.Future . 请改用 com.google.common.util.concurrent.ListenableFuture 或类似名称 . 使用 ListenableFuture s,您可以在 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

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

    这样做的好处是,它可以在你的任务开始后更好地控制你的任务的命运(我认为你正在做什么?) . 不过,这有点麻烦 . 您可以通过简单地存储有问题的 Future 对象的ID来处理成功任务和手动取消任务的情况 .

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

    有关 Map.Entry 接口的更多信息,请参阅Javadoc .

相关问题