我想创建一个具有固定线程池大小的singleton-ExecutorService。另一个线程将使用Callables提供ExecutorService,并且我想在执行完成后立即解析Callables的结果(最佳)。
我真的不确定如何正确实现这一点。 我最初的想法是singleton-ES中的一个方法,它通过“submit(callable)”将一个Callable添加到ExecutorService,并将生成的Future存储在单例内的HashMap或ArrayList中。另一个线程会在给定的时间间隔内检查Futures的结果。
但不知怎的,这个解决方案并没有“感觉正确”,而且我没有在其他地方找到这个用例的解决方案,所以在我编写我后悔的东西之前,我问你们。 你会如何处理这个问题?
我期待您的回复!
答案 0 :(得分:1)
您可以使用MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(THREAD_NUMBER));
创建服务
并使用guava ListenableFuture来解析结果,你也可以将自行车用于侦听未来的结果。
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
public Explosion call() {
return pushBigRedButton();
}
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Explosion explosion) {
walkAwayFrom(explosion);
}
public void onFailure(Throwable thrown) {
battleArchNemesis(); // escaped the explosion!
}
});
答案 1 :(得分:1)
import java.util.concurrent.*;
public class PostProcExecutor extends ThreadPoolExecutor {
// adjust the constructor to your desired threading policy
public PostProcExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable) {
@Override
protected void done()
{
if(!isCancelled()) try {
processResult(get());
} catch(InterruptedException ex) {
throw new AssertionError("on complete task", ex);
} catch(ExecutionException ex) {
// no result available
}
}
};
}
protected void processResult(Object o)
{
System.out.println("Result "+o);// do your post-processing here
}
}
答案 2 :(得分:1)
使用ExecutorCompletionService。这样,您可以在Callable
(s)准备就绪后立即获得结果。完成服务的take
方法阻止等待每个任务完成。
以下是来自java doc的示例:
void solve(Executor e,
Collection<Callable<Result>> solvers)
throws InterruptedException, ExecutionException {
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(e);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
use(r);
}
}
答案 3 :(得分:1)
您可以使用 ExecutorCompletionService 来实现它。
以下步骤可以帮助您。
使用 Runtime.getRuntime()。availableProcessors()填充可用处理器的数量。让我们将值保存在变量availableProcessors中。
初始化ExecutorService,例如 service = Executors.newFixedThreadPool(availableProcessors)
初始化ExecutorCompletionService,假设Callable的结果是整数数组整数[], ExecutorCompletionService completionService = new ExecutorCompletionService(service)
使用 completionService.submit 提交任务。
使用 completionService.take()。get()来获取任务的每个结果(可调用)。
根据以上步骤,您可以获得所有可调用的结果,并做一些您想要的业务。