我有我使用运行一堆工作线程来实现任务的并行执行包含多个组件的fixedThreadPool。
当所有线程都完成,我检索使用的方法(的getResult)他们的结果(这是相当大的),并将其写入文件。
最终,为了节省内存,可以看到中间结果,我想每一个线程,因为它执行完毕尽快写其结果到该文件,然后释放内存。
通常,我将代码添加到该效果的run()方法的结束。 然而,在这个类的某些其他对象也要求这些线程,但不希望他们写他们的成果文件 - 而不是他们用自己的结果来执行其它计算,这最终被写入文件。
所以,我在想,如果有可能的回调函数连接到使用的ExecutorService线程整理的事件。 这样的话,我可以马上检索其结果,并释放在该方案中的记忆,但是当这些线程在其它场景中使用未破解的代码。
这样的事情可能吗?
如果使用谷歌番石榴是一种选择,你可以利用ListenableFuture以下方式界面:
- 转换一个
ExecutorService
到ListeningExecutorService经由MoreExecutors.listeningDecorator(existingExecutorService)
- 在
submit(Callable<V>)
的方法ListeningExecutorService
已缩小到返回ListenableFuture
,这是一个子接口Future
。 -
ListenableFuture
拥有addListener()
方法,这样你就可以完成未来时注册一个回调来运行。
ExecutorService#submit
返回FutureTask<T>
它可以帮助您检索结果和ExecutorService#get
直至计算未完成方法将阻塞执行。 例如 -
ExecutorService executor = Executors.newFixedThreadPool(10);
Future<Long> future = executor.submit(new Callable<Long>(){
@Override
public Long call() throws Exception {
long sum = 0;
for (long i = 0; i <= 10000000l; i++) {
sum += i;
}
return sum;
}
});
Long result = future.get();
System.out.println(result);
所以,我在想,如果有可能的回调函数连接到使用的ExecutorService线程整理的事件。
不是直接的,没有,但也有一对夫妇,你可以做到这一点的方式。 我想到的最简单的方法是来包装你Runnable
在另一个Runnable
,做的结果收割。
所以,你会做这样的事情:
threadPool.submit(new ResultPrinter(myRunnable));
...
private static class ResultPrinter implements Runnable {
private final MyRunnable myRunnable;
public ResultPrinter(MyRunnable myRunnable) {
this.myRunnable = myRunnable;
}
public void run() {
myRunnable.run();
Results results = myRunnable.getResults();
// print results;
}
}
您可以添加一个回调时在Java中8+一个线程返回使用CompletableFuture
为以下,其中t
是长时间运行计算的结果,
int x = 10;
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(x);
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
}
});
哎呀,刚发现在计算器上答案:
在线程Java的ExecutorService的回调结束
感谢您的耐心!