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

mic*_*son 5 java multithreading future

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

在我的Java App中,我有一个threadExecutor对象,它定义了一个包含5个线程的Pool.

ExecutorService threadExecutor = Executors.newFixedThreadPool(5);
Run Code Online (Sandbox Code Playgroud)

一个sendCallables方法负责作业的列表分配给执行器.
我跟踪一个带有ObjectXList.通过这种方式,如果用户想要中断/取消线程,我可以引用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);
    ....
}
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.

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

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

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

我想在WeakHashMap中能够清理Map,一旦referenceObj不再被Application引用,但是这并没有阻止Futures被执行,因为我仍然需要在它们上调用.cancel()(一种与WeakHashMap关联的eventHandler remove(Object)方法?)

Mik*_*e Q 3

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

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

ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>();
Run Code Online (Sandbox Code Playgroud)

每次提交任务批次时执行此操作

new WeakReference<ObjectX>( referenceObj, refQ ).enqueue();
Run Code Online (Sandbox Code Playgroud)

有一个线程只运行此循环,该循环会拉出已变得弱可达(符合 GC 条件)的对象并取消 future/任务。

while (true)
{
    // this blocks
    ObjectX referenceObj = refQ.remove().get();
    cancelFutures( referenceObj );
}
Run Code Online (Sandbox Code Playgroud)