当前位置: 首页 > 面试题库 >

创建动态(增长/缩小)线程池

靳越
2023-03-14
问题内容

我需要在Java(java.util.concurrent)中实现一个线程池,该线程池在空闲时处于最小数量,在作业提交到其完成速度快于完成时会增长到一个上限(但永远不会超过上限)
,并且在完成所有作业且不再提交任何作业时,缩小到下限。

您将如何实现这样的目标?我想这将是一个相当普遍的使用场景,但是显然java.util.concurrent.Executors工厂方法只能创建固定大小的池,并且当提交许多作业时池会无限增长。本ThreadPoolExecutor类提供corePoolSizemaximumPoolSize参数,但它的文档似乎暗示只有这样才能不断有超过corePoolSize在同一时间线是采用有界作业队列,在这种情况下,如果你已经达到maximumPoolSize线程,你会得到工作您必须自己处理的拒绝?我想出了这个:

//pool creation
ExecutorService pool = new ThreadPoolExecutor(minSize, maxSize, 500, TimeUnit.MILLISECONDS,
    new ArrayBlockingQueue<Runnable>(minSize));
...

//submitting jobs
for (Runnable job : ...) {
    while (true) {
        try {
            pool.submit(job);
            System.out.println("Job " + job + ": submitted");
            break;
        } catch (RejectedExecutionException e) {
            // maxSize jobs executing concurrently atm.; re-submit new job after short wait
            System.out.println("Job " + job + ": rejected...");
            try {
                Thread.sleep(300);
            } catch (InterruptedException e1) {
            }
        }
    }
}

我在俯视什么吗?有一个更好的方法吗?另外,根据一个人的要求,上面的代码要等到至少(我认为)(total number of jobs) - maxSize工作完成后才能完成,这可能是有问题的。因此,如果您希望能够向池中提交任意数量的作业,并在不等待任何作业完成的情况下立即进行操作,那么我不知道如果没有专门的“作业汇总”线程来管理该作业,怎么办?保留所有已提交作业所需的无界队列。AFAICS,如果您对ThreadPoolExecutor本身使用无限制队列,则其线程数将永远不会超过corePoolSize。


问题答案:

可能会帮助您的一个技巧是分配一个RejectedExecutionHandler使用相同线程的作业,以将作业提交到阻塞队列。这将阻塞当前线程,并消除对某种循环的需要。

这是从该答案中复制的拒绝处理程序。

final BlockingQueue queue = new ArrayBlockingQueue<Runnable>(200);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(nThreads, nThreads,
       0L, TimeUnit.MILLISECONDS, queue);
// by default (unfortunately) the ThreadPoolExecutor will call the rejected
// handler when you submit the 201st job, to have it block you do:
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
   public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
      // this will block if the queue is full
      executor.getQueue().put(r);
   }
});

然后,您应该能够使用的核心/最大线程数的,只要你意识到有界阻塞队列你使用首先填满芯线上面创建的线程之前。因此,如果您有10个核心线程,并且希望第11个作业启动第11个线程,那么您将需要具有大小为0的阻塞队列(可能是a
SynchronousQueue)。我觉得这是本来不错的ExecutorService课程的真正限制。



 类似资料:
  • 我需要在Java(Java.util.concurrent)中实现一个线程池,它的线程数在空闲时处于某个最小值,当作业提交到线程池中时,线程数会增长到一个上限(但不会再增长),而当所有作业完成且不再提交作业时,线程数会收缩到下限。 您将如何实现这样的功能?我想这将是一个相当常见的使用场景,但显然是factory方法只能创建固定大小的池以及在提交多个作业时无限增长的池。类提供了和参数,但其文档似乎暗

  • 我正在写一个小的多线程超文本传输协议文件下载程序,并希望能够缩小可用的线程,因为代码遇到错误 这些错误将特定于在web服务器不允许任何更多连接的情况下返回的http错误 eg.如果我设置了一个由5个线程组成的池,每个线程都试图打开自己的连接并下载文件块。服务器可能只允许2个连接,我相信会返回503个错误,我想检测到这一点并关闭一个线程,最终限制池的大小,大概只有服务器允许的2个 我能让线自动停止吗

  • 本文向大家介绍ASP.NET创建动态缩略图的方法,包括了ASP.NET创建动态缩略图的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了ASP.NET创建动态缩略图的方法。分享给大家供大家参考。具体分析如下: 提示: 1. 导入 System.IO 2. 创建 类C lass "CreateThumbnails" or any class and place following func

  • 问题内容: 我有一个运行时间很长的过程,可以监听事件并进行一些激烈的处理。 目前,我通常用于限制并发运行的作业数量,但是根据一天中的时间以及其他各种因素,我希望能够动态地增加或减少并发线程的数量。 如果我减少了并发线程的数量,那么我希望当前正在运行的作业能够很好地完成。 是否有Java库可以让我控制并动态增加或减少线程池中运行的并发线程数?(该类必须实现ExecutorService)。 我必须自

  • 我的应用程序中有如下工作流:可以有X个用户请求(通常同时有5-10个),他们希望在系统中搜索某些东西(每个请求在单独的线程中处理)。 每个搜索都可以并行处理(我目前正在实现)。线程/CPU使用实际上不是这里的问题,因为这些任务不需要占用CPU。数据库是瓶颈。 目前,我只为搜索机制设置了一个单独的DB连接池-最大池大小设置为10。我知道这不多,但我不能把它设置得更高。现在我试图弄清楚如何为每个搜索(

  • 我有以下问题: 示例: 输入:[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]输出:6顺序:[0,2,6,9,13,15]或[0,4,6,9,11,15]或[0,4,6,9,11,15] 这是一个DP问题,我确实有一些问题在记忆步骤。下面是我的代码: 多谢了。