如何区分Java期货?

如何区分Java期货?,java,concurrency,java.util.concurrent,Java,Concurrency,Java.util.concurrent,看起来我应该能够区分未来,而不必维护两个哈希映射(或一个双向哈希) 当作业提交给ExecutorService时,未来是已知的。使用键“jobID”将未来添加到地图 若作业需要取消,请在映射中使用“jobID”检索Future并取消 如果作业成功完成,则可以通过返回的对象(包含作业ID)标识未来。通过“作业ID”从地图中删除未来 如果作业被中断或引发异常,则不会返回任何对象,因此必须通过调用Future.hashCode或Future.equals(因此,两个hashmap或一个双向第三方散列)

看起来我应该能够区分未来,而不必维护两个哈希映射(或一个双向哈希)

  • 当作业提交给ExecutorService时,未来是已知的。使用键“jobID”将未来添加到地图
  • 若作业需要取消,请在映射中使用“jobID”检索Future并取消
  • 如果作业成功完成,则可以通过返回的对象(包含作业ID)标识未来。通过“作业ID”从地图中删除未来
  • 如果作业被中断或引发异常,则不会返回任何对象,因此必须通过调用Future.hashCode或Future.equals(因此,两个hashmap或一个双向第三方散列)将Future与“jobID”匹配
  • 我是否遗漏了什么,或者这是预期的方法?我想覆盖Future以包含一个“getId”方法或其他东西,但基于执行者如何创建它们,这似乎不可行

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

    一种方法(我以前使用过)是创建一个
    HashMap
    ,它使用
    字符串作为键,使用
    映射.Entry
    作为值。您可以自己轻松地实现
    Map.Entry
    接口,但基本上它提供了一个元组结构,您可以使用它来存储
    未来的
    及其关联的
    hashCode

    这样做的好处是,一旦任务开始,它就可以更好地控制您的
    未来任务的命运(我想这就是您的目的)。不过这有点麻烦。您只需存储有问题的
    未来对象的ID,就可以处理成功任务和手动取消任务的情况

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


    有关
    Map.Entry
    界面的更多信息,请参阅。

    切勿使用
    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);
        ...
      }});
    
    ListenableFuture=MoreExecutors.listeningDecorator(executor)。提交(
    新的可调用(){
    @凌驾
    公共整数调用()引发异常{
    ...
    }
    });
    //将jobId添加到地图中。你应该使用线程安全的映射!
    map.put(jobId,future);
    Futures.addCallback(future,newfuturecallback(){
    @凌驾
    成功时的公共void(整数结果){
    map.remove(jobId);
    ...
    }
    @凌驾
    失效时的公共无效(可丢弃的t){
    map.remove(jobId);
    ...
    }});
    
    为什么不创建一个包装器对象,并将其作为一个成员字段?我不太清楚您想要实现什么。您正在寻找一种方法来取消一些
    未来的
    对象,中断其他对象并等待其他对象的完成?基本上这是一个作业管道。外部源将获得状态,并能够手动取消长期运行的作业。这份工作可能也会有例外:这是最难的部分,看起来应该更容易。如何在不使用两个散列图的情况下将未来链接回它所属的工作。广泛的笔划概括语句,如“永不使用此”是不好的,并且经常(在您的情况下)是错误的。有时会使用未来和不可列出的未来(尤其是第三方库)。如果你想说他不应该使用期货,那么就说为什么
    Future
    的方法集很差,没有能力在
    Future
    完成时注册回调,没有能力在
    Future
    失败时注册回退,没有能力为
    Future
    设置超时。谢谢-我现在就给你一个机会。能够用附加的jobId定义FutureCallback的子类已经让我更开心了。