1

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

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

在此先感谢您的帮助。任何指向有用的文档或示例的指针将不胜感激。

代码,供参考,虽然微不足道:

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();  
    }


}

4

1 回答 1

1

首先,Java 是CompletionService孤立的吗?

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

CompletionService其次,为每个请求创建这么多 s 是不是这种不好的做法?

我会说没关系。ACompletionService只不过是 executor 的一个相当薄的包装器。您必须忍受“开销”(BlockingQueue任务的内部和包装器实例),但它很小,您从中获得的收益可能比成本要多。有人可能会问你是否只需要一个来完成 2 到 3 个任务,但这有点取决于任务。在这一点上,这是一个关于 aCompletionService一般是否值得的问题,所以这取决于您来决定,因为它超出了您的问题范围。

于 2020-06-30T02:14:08.083 回答