Java多线程应用程序 - 如何动态取消Futures对象

时间:2010-03-26 14:22:28

标签: java multithreading future

我认为这是多线程Java应用程序的常见场景,因此我将尝试在此处进行描述。

在我的Java应用程序中,我有一个 threadExecutor 对象,它定义了一个包含5个线程的池。

ExecutorService threadExecutor = Executors.newFixedThreadPool(5);

sendCallables 方法负责将一份作业列表分配给执行者。
我使用 ObjectX 跟踪列表。通过这种方式,如果用户想要中断/取消线程,我可以引用Futures列表。像这样:

Map<ObjectX, List<Future<String>>> map = new HashMap<ObjectX, Future<String>>();

public void sendCallables(ObjectX referenceObj, List<Callable<String>> list) {
    ...
    List<Future<String>> futureList = new ArrayList<Future<String>>();
    for(Callable<String> myCallableJob : list) {
        Future<String> future = threadExecutor.submit(myCallableJob);
        futureList.add(future);
    }
    ...
    map.add(referenceObj, futureList);
    ...
}

public void cancelFutures(ObjectX referenceObj) {
    ...
    List<Future<String>> list = map.get(referenceObj);
    for(Future<String> future : list) {
        future.cancel();
    }
    map.remove(referenceObj);
    ....
}

到目前为止一切顺利。

现在有些情况下不再需要执行提交的任务
在这些情况下,应用程序应智能/自动地决定取消任务。
当用户会话到期或特定流程(与提交的任务相关)在执行所有作业之前结束时,可以在Web应用程序中找到此类情况的示例。

所以基本上我每次都需要调用cancelFutures(referenceObj),因为我的应用程序没有意义继续执行Jobs。我应该在应用程序需要调用它时识别每种情况。

我想知道是否有更好的方法来做到这一点。

我想在WeakHashMap中能够在应用程序不再引用referenceObj时清理Map,但这并不能阻止Futures执行,因为我仍然需要调用.cancel( )on this(一种与WeakHashMap删除(Object)方法相关联的eventHandler?)

2 个答案:

答案 0 :(得分:3)

我认为你提出的解决方案非常好。如果你真的,真的想从referenceObj驱动取消垃圾收集,那么你可以使用WeakReference和ReferenceQueue的组合。

在执行助手类中声明其中一个。

ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>();

每次提交任务批次时都这样做

new WeakReference<ObjectX>( referenceObj, refQ ).enqueue();

拥有一个只运行此循环的线程,该线程将拉出易于访问的对象(符合GC条件)并取消期货/任务。

while (true)
{
    // this blocks
    ObjectX referenceObj = refQ.remove().get();
    cancelFutures( referenceObj );
}

答案 1 :(得分:0)

如果我正确理解您的问题,您会发生各种类型的活动,并且您不希望将这些活动联系起来只是因为它们可以被取消。

听起来,每个需要取消的案例都应该触发一个事件。事件监听器会监听这些事件并取消相关的Future

关于会话的示例 - 您将拥有一个实现javax.servlet.http.HttpSessionListner的类,检测需要取消的相关任务并触发事件以取消这些任务。由于所有内容都是异步的,因此您无需关心已取消的任务是否已完成,因此不会丢失任何内容。