Java 如何处理失败的期货

Java 如何处理失败的期货,java,multithreading,future,Java,Multithreading,Future,我正在与一个我无法控制的遗留库集成 它定义了以下接口: interface Factory { Future<Void> subscribe(Context c); } 这种方法的缺点是,我们仍然在阻塞一个线程很长一段时间。正如我所说,这个代码片段将被频繁执行 方法2: 获取Future的实例后,将其放置到某个集合中,并指定一个单独的线程,该线程将定期运行此集合中的元素进行处理: while(true){ Iterator<Future<

我正在与一个我无法控制的遗留库集成

它定义了以下接口:

interface Factory {
    Future<Void> subscribe(Context c);
}
这种方法的缺点是,我们仍然在阻塞一个线程很长一段时间。正如我所说,这个代码片段将被频繁执行

方法2:

获取Future的实例后,将其放置到某个集合中,并指定一个单独的线程,该线程将定期运行此集合中的元素进行处理:

    while(true){
        Iterator<Future<Void>> iterator = collection.iterator();
        while(iterator.hasNext()){
            Future<Void> future = iterator.next();
            if(future.isDone()){
                try {
                    future.get();
                } catch(Exception e){
                    // process the exception
                } finally {
                    iterator.remove();
                }
            }
        }

        TimeUnit.MILLISECONDS.sleep(1000); // sleep
    }
while(true){
迭代器迭代器=collection.Iterator();
while(iterator.hasNext()){
Future=iterator.next();
if(future.isDone()){
试一试{
future.get();
}捕获(例外e){
//处理异常
}最后{
iterator.remove();
}
}
}
时间单位。毫秒。睡眠(1000);//睡眠
}

你觉得怎么样?是否有更好的方法解决此问题?

由于您无法创建
未来
最佳选项不可用,请使用自定义的
未来
未来
本身触发处理

所以在你的例子中,我推荐一种模式,它看起来可能是你两种选择的混合体。将
Future
s添加到(线程安全)队列中,并将
Runnable
s提交给处理循环中所有项目的执行器。因此,您可以通过配置
执行器
来限制线程的数量,也就是说,没有
未来
那么多的线程,但仍然可以有多个线程,并且不必让这些后处理线程一直处于活动状态

为了避免在对未完成的项目重新排队时出现无限循环,请使用本地集合将挂起的项目与重新排队的项目分开:

static BlockingQueue<Future<?>> PENDING = …;
static int MAX_ITEMS_PER_JOB = …;
…
/*scheduling code …*/new Runnable() {
  public void run()
  {
    ArrayList<Future<?>> myLocalItems=new ArrayList<>();
    PENDING.drainTo(myLocalItems, MAX_ITEMS_PER_JOB);
    for(Future<?> f:myLocalItems) {
      if(!f.isDone()) PENDING.offer(f); // re-queue
      try {
        f.get();
      } catch(ExecutionException ex) {
        handleException(ex.getCause());
      }
    }
  }
};
static BlockingQueue>myLocalItems=newArrayList();
挂起.drainTo(myLocalItems,每个作业的最大项目数);
用于(未来f:myLocalItems){
如果(!f.isDone())挂起。提供(f);//重新排队
试一试{
f、 get();
}捕获(ExecutionException ex){
handleException(例如getCause());
}
}
}
};
因此,此
Runnable
将检查并处理有限数量的
未来
s,然后返回,因此,如果有很多项处于挂起状态,则可以多次提交以进行并行处理,但如果挂起的项数较少,则不会造成任何伤害,因为如果无事可做,作业将不会挂起。它们甚至适用于使用
ScheduledExecutorService
的带有固定延迟的
scheduledelay

static BlockingQueue<Future<?>> PENDING = …;
static int MAX_ITEMS_PER_JOB = …;
…
/*scheduling code …*/new Runnable() {
  public void run()
  {
    ArrayList<Future<?>> myLocalItems=new ArrayList<>();
    PENDING.drainTo(myLocalItems, MAX_ITEMS_PER_JOB);
    for(Future<?> f:myLocalItems) {
      if(!f.isDone()) PENDING.offer(f); // re-queue
      try {
        f.get();
      } catch(ExecutionException ex) {
        handleException(ex.getCause());
      }
    }
  }
};