Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何确定ThreadPoolTaskExecutor池和队列大小?_Java_Spring_Multithreading_Threadpool - Fatal编程技术网

Java 如何确定ThreadPoolTaskExecutor池和队列大小?

Java 如何确定ThreadPoolTaskExecutor池和队列大小?,java,spring,multithreading,threadpool,Java,Spring,Multithreading,Threadpool,这可能是一个更一般的问题,关于如何决定线程池大小,但是让我们使用SpringThreadPoolTaskExecutor来解决这个问题。对于池核心、最大大小和队列容量,我有以下配置。我已经阅读了所有这些配置的含义——有一个很好的答案 以上数字在我看来是随机的,我想了解如何根据我的环境正确设置它们。我将概述以下约束条件: 该应用程序将在一个双核CPU机箱上运行 执行者将执行一项通常需要1-2小时的任务 还有几秒钟就要结束了 通常我希望800个/分钟的任务提交给我的执行者,峰值为2500个/分钟 该

这可能是一个更一般的问题,关于如何决定线程池大小,但是让我们使用Spring
ThreadPoolTaskExecutor
来解决这个问题。对于池核心、最大大小和队列容量,我有以下配置。我已经阅读了所有这些配置的含义——有一个很好的答案

以上数字在我看来是随机的,我想了解如何根据我的环境正确设置它们。我将概述以下约束条件:

  • 该应用程序将在一个双核CPU机箱上运行
  • 执行者将执行一项通常需要1-2小时的任务 还有几秒钟就要结束了
  • 通常我希望800个/分钟的任务提交给我的执行者,峰值为2500个/分钟
  • 该任务将构造一些对象并对GooglePubSub进行HTTP调用

  • 理想情况下,我想了解我需要考虑的其他约束条件,基于这些规则,我的池和队列大小将是一个合理的配置。

    < P> Update:这个答案在过去几年中得到了一些选票,所以我给那些没有时间读我奇怪的隐喻的人添加了一个缩短的版本:

    TL;博士回答:

    实际的限制是(逻辑)CPU核心只能同时运行单个线程。因此:

    • 内核数量:CPU的逻辑内核数量*1/(执行任务时线程的可运行比率)
    因此,如果您的机器上有8个逻辑内核,那么您可以安全地将8个线程放入线程池(记住,要排除可能使用的其他线程)。然后你需要问自己是否可以投入更多:你需要对你打算在线程池上运行的任务类型进行基准测试:如果你注意到线程平均只运行50%的时间,这意味着你的CPU可以在另一个线程上自由工作50%的时间,你可以添加更多的线程

    • 队列大小:尽可能多地等待
    队列大小是线程池在拒绝之前将接受的项目数。这是商业逻辑。这取决于你期望的行为:接受十亿个任务有意义吗?你什么时候扔毛巾? 如果一个任务需要一秒钟才能完成,而您有10个线程,这意味着队列中的第10000个任务有望在1000秒内完成。可以接受吗? 最糟糕的情况是客户端超时并在完成第一个任务之前重新提交相同的任务

    原始ELI12答案:

    这可能不是最准确的答案,但我会尝试:

    一个简单的方法是要知道,您的2核CPU将只能同时在两个线程上工作

    如果您有相对现代的英特尔CPU,并且启用了超线程(又称HT(TM),HTT(TM),SMT),则操作系统将看到可用内核的数量是CPU中物理内核数量的两倍

    不管是哪种方式,从Java检测您可以使用多少个内核(或者同时不抢占其他线程),只需调用
    int cores=Runtime.getRuntime().availableProcessors()

    如果您试图将您的应用程序视为一个研讨会(实际研讨会):

    • 处理者将由员工代表。它是为产品增加价值的物理单元
    • 一项任务是一块原材料(加上一些说明清单)
    • 你的线程是一张桌子,员工可以把任务放在上面工作
    • 队列大小是将原材料运送到办公桌的传送带的长度
    因此,你的问题变成了“在员工数量不变的情况下,我如何选择工厂内有多少张办公桌以及传送带的长度?”

    关于多少张桌子(线)部分:

    员工一次只能在一张办公桌上工作,每个办公桌上只能有一名员工。因此,基本的设置是至少有和员工一样多的办公桌(以避免任何员工(处理者)被遗漏而无法工作)

    但是根据您的活动,您可以为每位员工提供更多的办公桌:

    如果你的员工需要经常将邮件放入信封中,这需要他们全神贯注的操作(在编程中:分类收集、创建对象、增加计数器),拥有更多的办公桌不会有任何帮助,甚至可能是有害的,因为你的员工必须这样做 有时更换办公桌(切换上下文,这需要一些时间),从而离开他们正在处理的办公桌,在另一个办公桌上取得工作进展

    但是,如果您的任务是制作陶器,并且依赖于您的员工在烤箱中等待粘土烹饪(了解如何访问外部资源,如文件系统、web服务等),那么您的员工可以在另一张桌子上制作粘土模型,稍后再回到第一张桌子

    因此,只要您的任务的有效工作/等待比率(运行/等待)足够大,您就可以为每位员工提供更多的办公桌。办公桌的数量是指您的员工在等待时间内可以完成多少任务

    对于传送带(队列)尺寸部件:

    队列大小表示在开始拒绝任何其他任务(通过抛出异常)之前允许排队的项目数,因此是开始告诉“好的,我已经超额预订了,永远无法遵守”的阈值

    首先,我要说的是,你的传送带需要安装在车间内。这意味着收集应该足够小,以防止内存不足错误(显然)

    在那之后,它是基于你们公司的政策
        @SpringBootApplication
        @EnableAsync
        public class MySpringBootApp {
    
            public static void main(String[] args) {
                ApplicationContext ctx = SpringApplication.run(MySpringBootApp.class, args);
            }
    
            @Bean
            public TaskExecutor taskExecutor() {
                ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
                executor.setCorePoolSize(5);
                executor.setMaxPoolSize(10);
                executor.setQueueCapacity(25);
                return executor;
            }
    
        }