首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一个线程池的多个CompletionService

一个线程池的多个CompletionService
EN

Stack Overflow用户
提问于 2020-06-29 23:54:53
回答 1查看 294关注 0票数 1

我正在开发一个具有以下一般架构的Java服务器应用程序:

  • 客户端向服务器发出RPC请求。
  • 我认为RPC服务器(gRPC)有自己的线程池来处理请求。
  • 请求将立即插入Thread Pool 1以进行更多处理。
  • 一个特定的请求类型,我们将调用Request R,需要并行运行几个异步任务,判断结果以形成一个共识,即它将返回给客户端。这些任务运行时间较长,因此我使用单独的Thread Pool 2来处理这些请求。重要的是,每个Request R都需要运行相同的2-3个异步任务。因此,Thread Pool 2服务于所有当前正在执行的Request R。然而,Request R只应该能够看到和检索属于它的异步任务。
  • 为了实现这一点,在每个传入的Request R上,而在Thread Pool 1中,它将为请求创建一个由Thread Pool 2支持的新CompletionService。它将提交2-3个异步任务,并检索结果。应该严格地将它们与其他属于其他请求的Thread Pool 2中可能运行的任何东西隔离开来。
  • 我的问题:
    • 首先,Java的CompletionService是孤立的吗?在检查了JavaDocs之后,我找不到关于这方面的好文档。换句话说,如果两个或多个CompletionService由相同的线程池支持,那么它们中的任何一个是否有可能提取属于另一个CompletionService的未来?
    • 第二,为每个请求创建这么多CompletionService是一种糟糕的做法吗?是否有更好的方法来处理这个问题?当然,为每个请求创建一个新的线程池是个坏主意,那么在CompletionService中是否有一种更规范/更正确的方法来隔离未来,或者我的做法还好吗?

提前谢谢你的帮助。任何有帮助的文档或检查的指针都将不胜感激。

代码,以供参考,尽管是微不足道的:

代码语言:javascript
复制
public static final ExecutorService THREAD_POOL_2 =
        new ThreadPoolExecutor(16, 64, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

// Gets created to handle a RequestR, RequestRHandler is run in Thread Pool 1
public class RequestRHandler {

    CompletionService<String> cs;

    RequestRHandler() {
        cs = new ExecutorCompletionService<>(THREAD_POOL_2);
    }

    String execute() {
        cs.submit(asyncTask1);
        cs.submit(asyncTask2);
        cs.submit(asyncTask3);

       // Lets say asyncTask3 completes first
      Future<String> asyncTask3Result = cs.take();

      // asyncTask3 result indicates asyncTask1 & asyncTask2 results don't matter, cancel them
      // without checking result


      // Cancels all futures, I track all futures submitted within this request and cancel them,
      // so it shouldn't affect any other requests in the TP 2 pool
      cancelAllFutures(cs);


      return asyncTask3Result.get();  
    }


}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-30 02:14:08

首先,Java的CompletionService是孤立的吗?

这不是固定的,因为它是一个接口,所以实现决定了。但是,由于唯一的实现是ExecutorCompletionService,我只想说答案是:是的。ExecutorCompletionService的每个实例在内部都有一个BlockingQueue,其中已完成的任务在其中排队。实际上,当您在服务上调用take时,它只是通过调用队列上的take将调用传递给队列。每个提交的任务都由另一个对象包装,该对象在任务完成时将任务放在队列中。因此,每个实例都管理它从其他实例中分离出来的提交任务。

第二,为每个请求创建这么多CompletionService是一种错误的做法吗?

我会说没关系的。CompletionService只不过是一个很薄的执行器包装器。您必须忍受“开销”(任务的内部BlockingQueue和包装器实例),但是它很小,而且您可能从它获得的收益超过了它的成本。如果你只需要2到3个任务,你可能会问你是否需要一个,但这在一定程度上取决于任务。在这一点上,这是一个关于CompletionService是否值得这样做的问题,所以这取决于您的决定,因为它超出了您的问题范围。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62648336

复制
相关文章

相似问题

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