Java 8中如何让异步任务具有较低的优先级?

use*_*412 5 java multithreading asynchronous java-8

我有一个处理主实体的服务,检索与主实体关联的第一个子实体,然后返回两者。它还启动了一组可完成的Future链,以出去并检索任何其他实体。目前,我只是采用一组预先构建的检索任务,将Future异步包装在它们周围,然后使用CachedThreadPool. 这很好,但是当超过 50 个用户访问服务器时,主要任务(检索主实体和第一个子实体)会因所有异步线程的运行而显着减慢。

我想知道是否有一种方法可以使异步调用以较低的优先级运行,以确保快速处理主要调用。

  public CompletableFuture buildFutureTasks(P primaryEntity, List<List<S>> entityGroups)
  {
    ExecutorService pool = Executors.newCachedThreadPool();
    CompletableFuture<Void> future = null;
    for (List<S> entityGroup : entityGroups)
    {
      if (future == null || future.isDone())
      {
        future = CompletableFuture.runAsync(() ->
            retrieveSubEntitiesForEntity(primaryEntity, entityGroup), pool);
      }
      else
      {
        future.thenRunAsync(() ->
            retrieveSubEntitiesForEntities(primaryEntity, entityGroup), pool);
      }
    }
    return future;
  }
Run Code Online (Sandbox Code Playgroud)

这是我在 50 多个用户的情况下运行的最快速度,但它仍然大大减慢了我添加的更多用户的速度。

St.*_*rio 3

正如您很可能已经知道的那样,有一种方法Thread::setPriority。但至于JavaDoc

每个线程都有一个优先级。具有较高优先级的线程优先于具有较低优先级的线程执行。

因此,您只需ThreadFactory在创建缓存时 提供一个ExecutorService. 实际的线程调度细节是特定于虚拟机实现的,所以你不能真正依赖它。我会考虑使用fixedThreadPool代替

但我不确定实际的问题是关于线程调度和优先级。首先,缓存线程池可以(至文档)

创建一个线程池,该线程池根据需要创建新线程,但会重用以前构造的线程(当它们可用时)。

如果有 50 多个用户可以调用,buildFutureTasks您无法真正控制创建的线程数量。

  1. 我会考虑使用fixedThreadPool,这样您就可以控制是否真的需要SynchronousQueue哪个是缓存线程池的底层。

  2. ThreadPool考虑对所有任务使用相同的方法,而不是buildFutureTasks每次调用方法时都在方法内创建它。

  • @user1760412 这取决于任务。如果您的任务是 CPU 密集型计算,那么没有理由创建超过“Runtime.getRuntime().availableProcessors()”的内容。但是,如果任务例如在远程主机上提交一些作业并等待结果...您很可能会创建 3 x `Runtime.getRuntime().availableProcessors()` 或更多池大小。 (3认同)