Java 从 ExecutorService 设置回调

我有一个固定的ThreadPool,我用它来运行一堆工作线程,以实现具有许多组件的任务的并行执行。

当所有线程都完成后,我使用方法(getResult)检索它们的结果(非常大)并将它们写入文件。

最终,为了节省内存并能够看到中间结果,我希望每个线程在完成执行后立即将其结果写入文件,然后释放其内存。

通常,我会将代码添加到 run() 方法的末尾。但是,此类中的某些其他对象也调用这些线程,但不希望它们将其结果写入文件 - 相反,它们使用其结果来执行其他计算,这些计算最终将写入文件。

所以,我想知道是否可以使用ExecutorService将回调函数附加到线程完成的事件。这样,我可以立即检索其结果并释放该方案中的内存,但在其他方案中使用这些线程时不会中断代码。

这样的事情可能吗?


答案 1

如果可以选择使用Google Guava,则可以通过以下方式使用ListenableFuture界面:

  1. 通过以下方式将 a 转换为侦听执行器服务ExecutorServiceMoreExecutors.listeningDecorator(existingExecutorService)
  2. 的方法已缩小到返回 a ,它是 的子接口。submit(Callable<V>)ListeningExecutorServiceListenableFutureFuture
  3. ListenableFuture有一个方法,因此您可以注册一个回调,以便在将来完成时运行。addListener()

答案 2

当线程在 Java 8+ 中返回时,您可以使用如下方式添加回调,其中是长时间运行的计算的结果,CompletableFuturet

CompletableFuture.supplyAsync(() -> {
    T t = new T();
    // do something
    return t;
}).thenApply(t -> {
    // process t
});

如果你想在Java 7中使用回调,你可以做这样的事情:

int x = 10;
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(x);
Future<T> result = fixedThreadPool.submit(() -> {
    // do calculation
    return T;
});
fixedThreadPool.submit(() -> {
    long minutesToWait = 5;
    T t = null;
    try {
        t = result.get(minutesToWait, TimeUnit.MINUTES);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        LOGGER.error(e);
    }
    if (t != null) {
        // process t
    }
});

推荐