速率限制执行器中的线程数 (Java)

Rate limiting the number of threads in an Executor (Java)

如何限制Executor中执行的线程数?例如,在下面的代码中:

            executor = Executors.newFixedThreadPool(this.noOfThreads);
            for (int i = 0; i < sections.size(); i++) {
                DomNode section = sections.get(i);
                // Retrieve the url of the subsection
                String subsectionUrl = section.getNodeValue();

                if(i != 0 && (i % noOfThreadsPerSection == 0)) {
                    // Add section threads to the executor
                    executor.execute(new BrowseSection(filter, webClient, subsectionUrl));
                } else {
                    executor.shutdown();
                    try {
                        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                    } catch (InterruptedException e) {
                        // We should normally never get here
                    }
                }
            }

调用executor.execute()时,如果线程池中充满了运行个线程会怎样?

上面的代码并没有检查线程是否还在执行器中运行,而是检查了已经启动的线程数。

来自 java 文档 newFixedThreadPool 有一个无界队列,因此所有其他线程都将等待:

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.

无论有没有事,池都会创建固定数量的线程。它不会根据您的使用方式而改变。

您的作业被传递到队列,线程池从队列中获取任务。当池不全忙时,任务几乎在添加后立即从队列中拉出。当您有更多任务时,队列会变长。

在 Java8 中,它避免为每个项目创建任务,而是将工作分解为多个部分。这样它可以比以简单的方式使用 ExecutorService 更有效。

在 Java 8 你会写。

sections.parallelStream()
        .map(s -> s.getNodeValue())
        .forEach(s -> new BrowseSection(filter, webClient, s).run());

不需要启动和关闭线程池等,等待所有任务完成。

您可以通过在命令行上设置

来更改ForkJoinPool.commonPool()的大小
-Djava.util.concurrent.ForkJoinPool.common.parallelism=N

您也可以在 class 加载之前进行实用设置。

Executors & ExecutorService没有提供APIs来控制任务队列大小,默认是无界的.

如果您的任务需要较短的时间间隔,则使用 ExecutorService 即可。

更喜欢ThreadPoolExecutor,它提供更好的TaskQueueSize控制,拒绝处理机制。

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)

您可以使用以下方法动态控制线程池大小 API

setCorePoolSize(newLimit)

查看这些 SE 问题了解更多详情: