当前位置: 首页 > 知识库问答 >
问题:

ThreadPoolExecitor在低负载时不收缩

程景胜
2023-03-14

在我的程序中,大多数时间任务很少提交给执行者,但它们并没有完全停止。当一次提交多个任务时,会出现周期性突发。

即使设置了allowCoreThreadTimeOut,并且在大多数情况下只有一个线程就足够了,但冗余的执行器线程不会停止。

这是因为执行器阻塞队列的公平性:当多个线程等待它时,所有线程都有同等的机会获得一个任务,并且它们的空闲时间不会显著增长。

有解决方法吗?例如,在多个等待线程的情况下,一个队列会在id最低的线程中返回?

public class ShrinkTPE {

    public static void main(final String[] args) throws Exception {
        final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
                .newFixedThreadPool(NTHREADS);
        executor.setKeepAliveTime(ALIVE_TIME, TimeUnit.SECONDS);
        executor.allowCoreThreadTimeOut(true);

        // thread alive time is 10s
        // load all threads with tasks at start and every 12s
        // also submit one task each second
        for (int i = 0;; i++) {
            int j = 0;
            do {
                if (false && !mostThreadsUnused(i))
                    break;
                final int i2 = i, j2 = j;
                executor.submit(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        System.out.println(""
                                + Thread.currentThread().getName() + " " + i2
                                + " " + j2);
                        Thread.sleep(300);
                        return null;
                    }
                });
            } while (mostThreadsUnused(i) && ++j < NTHREADS);
            Thread.sleep(1000);
            System.out.println();
        }
    }

    private static boolean mostThreadsUnused(final int i) {
        return i % (ALIVE_TIME + 2) == 0;
    }

    private static final int NTHREADS = 5;

    private static final int ALIVE_TIME = 10;
}

共有2个答案

宇文灿
2023-03-14

newCachedThreadPool的官方JDK实现如下所示。如果您想设置最大线程池大小或自定义保留AliveTime或使用不同的队列,您可以简单地直接调用该构造函数。

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
皇甫雨石
2023-03-14
final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(N_THREAD);

您使用的是固定线程池,这意味着,该池将始终有N_THREAD线程数。

使用不同的线程池,也许是CachedThreadPool?它会重用现有线程,但如果您向池中提交新任务,它会启动额外的线程,并且不会有空闲线程。

空闲线程在X个时间后死亡(默认为60秒空闲)

 类似资料:
  • 介绍 Pacemaker 是一个旨在处理 worker 心跳的 storm 守护进程. 随着 storm 的扩大, ZooKeeper 由于 worker 进行心跳的大量写入而开始成为瓶颈. 当 ZooKeeper 尝试维护一致性时, 会产生大量写入磁盘和跨网络的流量. 因为心跳是短暂的, 它们不需要被持久化到磁盘或跨节点同步; 会在内存的存储中来做. 这是 Pacemaker 的作用. Pace

  • 我们目前对应用程序的负载测试是使用jMeter完成的,到目前为止运行良好。我们有三个不同的线程组,可以通过命令行标志分别启用和配置。还可以从命令行配置线程数和目标吞吐量。 我正在寻找的是为每个线程组编程负载场景的可能性。通常jMeter启动所有线程,然后尝试达到其目标吞吐量速率。我想要实现的如下:我配置目标吞吐量速率为每秒500个请求,启动速率为20,增量为20,持续时间为5分钟。jMeter应该

  • 我目前正在将我的应用程序从WAS 8迁移到WAS Liberty,我遇到了以下问题。在我的一个模块网页中。xml文件中,servlet启动时的加载值为-1。在Liberty中运行时,不会调用特定的servlet。有人能帮我吗?请从我的web.xml<code>中找到以下代码片段

  • 我刚开始使用Sheets API,并按照以下设置创建新的工作表:https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/create 在此代码中,spreadsheetBody对象为空。为此,我使用了本页上的示例:https://developers.google.com/sheets/api/samples/

  • 负载的实现方式有很多种,Uragano采用客户端集成负载,目前支持负载算法有轮询、加权轮询、随机、加权随机、Hash一致性。在未指定负载算法的情况下,Uragano默认采用轮询。 service.AddUragano(context.Configuration, builder => { builder.Add

  • 我正在运行一个简单的web应用程序,它为每个请求使用一些web服务,我发现我们的服务器发出的请求有时会超时(合成599错误),即使其他服务在任何时候都有响应(我已经验证了这一点)。 以下是我收到的错误消息: (连接时超时) (接收数据前超时) (数据部分传输时超时) 我已经能够在两个不同的环境中重现这一点,一个是AmazonEC2mi实例,另一个是MacBookPro(i7)。在EC2实例中,只有