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());
}
}
}
};