是否有更好的选择(设计/性能/内存优化)来替代我在下面使用的内容:
问题陈述:在J2EE环境中,当请求出现时,我的控制器需要从三个不同的服务(例如)中获取数据。第一次获得天气数据,第二次获得交通密度,最后一次得到目前访问我们的外星人的数量)。如果一个服务需要大约5秒(最好的情况下)来获取,那么以同步的方式,它们至少需要15 Sec。但控制器不应超过6-7秒.所以最终会调用不同的线程。但是,在某些情况下,服务花费超过10秒(可能是最坏的情况)。
ForkJoinPool”实例--而不是在每个请求上创建它。创建了一个自定义类(例如ForkService),扩展了具有List<RecursiveAction>的RecursiveAction。而ForkService的计算方法@Override
protected void compute() {
for (RecursiveAction recursiveAction : actions) {
recursiveAction.fork(); // async calling of all other service's compute method which actually fetches the data from the relevant service.
}
mPool.shutdown();
}目前使用这种方法,效果很好。想知道有什么更好的方法吗?
发布于 2015-01-09 20:34:34
一种简单而优雅的方法是使用固定线程池和番石榴的ListenableFuture,您可以在其中调用Futures.successfulAsList
private MyResult getResult(MyRequest request) {
ExecutorService es = Executors.newFixedThreadPool(3);
ListeningExecutorService les = MoreExecutorslisteningDecorator(es);
ListenableFuture<?> lf1 = les.submit(getCallableForService1(request));
ListenableFuture<?> lf2 = les.submit(getCallableForService2(request));
ListenableFuture<?> lf3 = les.submit(getCallableForService3(request));
ListenableFuture<List<?>> lfs = Futures.successfulAsList(lf1, lf2, lf3);
// wait 7 sec for results
List<?> res = lfs.get(7, TimeUnit.SEONDS);
return extractRes(res);
}当然,您应该处理Callable的正确类型。
发布于 2015-01-09 20:58:58
我对叉/连接框架不太熟悉,但我可以马上告诉您,为每个请求创建一个新的线程池会使线程池的功能降低一半。创建和销毁线程非常昂贵,使用线程池可以重用线程。
从文档来看,Fork/Join似乎是针对本质上是递归的、需要进行密集处理的问题设计的。你的问题似乎不符合这些标准。
使用所有请求共享的常规ThreadPoolExecutor可能会更好。invokeAll方法可能特别有用;您可以同时提交所有3个请求,接收一个List<Future<T>>,甚至可以提供一个超时。
要获得结果,您可以简单地遍历List<Future<Thing>> things
Thing[] results = new Thing[3];
for (int i = 0; i < things.size(); ++i) {
results[i] = things.get(i).get();
}发布于 2017-03-02 20:17:15
已经有一段时间了,但是想写一些其他的选择:
RecursiveAction的使用。ListenableFuture。https://stackoverflow.com/questions/27868451
复制相似问题