首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >J2EE环境.多线程并行从不同服务中获取数据

J2EE环境.多线程并行从不同服务中获取数据
EN

Stack Overflow用户
提问于 2015-01-09 20:12:14
回答 3查看 310关注 0票数 2

是否有更好的选择(设计/性能/内存优化)来替代我在下面使用的内容:

问题陈述:在J2EE环境中,当请求出现时,我的控制器需要从三个不同的服务(例如)中获取数据。第一次获得天气数据,第二次获得交通密度,最后一次得到目前访问我们的外星人的数量)。如果一个服务需要大约5秒(最好的情况下)来获取,那么以同步的方式,它们至少需要15 Sec。但控制器不应超过6-7秒.所以最终会调用不同的线程。但是,在某些情况下,服务花费超过10秒(可能是最坏的情况)。

  1. 因此,我想创建一个线程等待,使用一个小状态维护的可观察模式通知。这是可行的,但不满意的设计。
  2. 然后我找到了Java 'ForkJoinPool‘。对于每个请求控制器,创建一个新的“ForkJoinPool”实例--而不是在每个请求上创建它。创建了一个自定义类(例如ForkService),扩展了具有List<RecursiveAction>RecursiveAction。而ForkService的计算方法
代码语言:javascript
复制
@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();
    }

目前使用这种方法,效果很好。想知道有什么更好的方法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-09 20:34:34

一种简单而优雅的方法是使用固定线程池和番石榴的ListenableFuture,您可以在其中调用Futures.successfulAsList

代码语言:javascript
复制
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的正确类型。

票数 2
EN

Stack Overflow用户

发布于 2015-01-09 20:58:58

我对叉/连接框架不太熟悉,但我可以马上告诉您,为每个请求创建一个新的线程池会使线程池的功能降低一半。创建和销毁线程非常昂贵,使用线程池可以重用线程。

从文档来看,Fork/Join似乎是针对本质上是递归的、需要进行密集处理的问题设计的。你的问题似乎不符合这些标准。

使用所有请求共享的常规ThreadPoolExecutor可能会更好。invokeAll方法可能特别有用;您可以同时提交所有3个请求,接收一个List<Future<T>>,甚至可以提供一个超时。

要获得结果,您可以简单地遍历List<Future<Thing>> things

代码语言:javascript
复制
Thing[] results = new Thing[3];
for (int i = 0; i < things.size(); ++i) {
    results[i] = things.get(i).get();
}
票数 1
EN

Stack Overflow用户

发布于 2017-03-02 20:17:15

已经有一段时间了,但是想写一些其他的选择:

  1. 回调的使用。当线程完成工作时,它通过回调进行响应。
  2. 通知:每个线程在完成工作时发送一个通知。
  3. 问题中提到的RecursiveAction的使用。
  4. 答案被接受为最终答案,在那里它使用番石榴库的ListenableFuture
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27868451

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档