Java 使用多个线程池和连接池

Java 使用多个线程池和连接池,java,threadpool,connection-pooling,Java,Threadpool,Connection Pooling,我目前正在使用5个线程池,我想为这些池找到最佳大小。这是某种先验分析。池按用途划分:用于处理命令(cmdPool)、处理库存事务(invPool)、数据库事务池(dbPool)以及仅需运行异步I/O(fastPool)和计划任务(timerPool)的普通事务池。我还没有任何可以用来解决问题的统计数据 对于数据库查询,我使用带有默认值的HikariCP。稍后,我将尝试更改最大连接数和最小空闲连接数,以找到最佳性能。但现在,当使用Hikari池时,它总是从一个池中调用,以不影响主线程。通常的数据库

我目前正在使用5个线程池,我想为这些池找到最佳大小。这是某种先验分析。池按用途划分:用于处理命令(cmdPool)、处理库存事务(invPool)、数据库事务池(dbPool)以及仅需运行异步I/O(fastPool)和计划任务(timerPool)的普通事务池。我还没有任何可以用来解决问题的统计数据

对于数据库查询,我使用带有默认值的HikariCP。稍后,我将尝试更改最大连接数和最小空闲连接数,以找到最佳性能。但现在,当使用Hikari池时,它总是从一个池中调用,以不影响主线程。通常的数据库查询是在dbPool下调用的,但仅当代码块不是已提交到其中一个线程池中的runnable的一部分时才调用

实际安装看起来它在应用程序中正常工作。因此,我的问题是:

1.)当我决定停止使用cachedThreadPool,并将pool与一些最小空闲线程(如timerPool)一起使用,或者我应该坚持使用cachedThreadPool时,会对性能和资源产生怎样的影响

2.)设置最大池大小是正确的解决方案,以防止在短时间内有100个客户端加入时出现峰值,并让它们在其他任务完成时保持短时间等待

3.)有没有更好的解决方案来管理多种任务

cmdPool = Executors.newFixedThreadPool(3);
invPool = Executors.newFixedThreadPool(2);
dbPool = Executors.newCachedThreadPool();
fastPool = Executors.newCachedThreadPool();
timerPool = new ScheduledThreadPoolExecutor(5);
timerPool.allowCoreThreadTimeOut(true);
timerPool.setKeepAliveTime(3, TimeUnit.MINUTES); 
因此,首先,每个操作都取决于连接了多少个客户端,让我们假设值为5-25个客户端。池的设计应该能够维持100个客户端这样的极端情况,并且不会在短时间内产生太多线程

预期用途可能会有所不同,并且每秒都不相同,即使可能发生,也不会运行任何任务。cmdPool的预期使用率为每秒3-8次(轻量级任务)。For invPool的使用率与cmdPool每秒2-6次的使用率(也是轻量级任务)几乎相同。至于dbPool,这比所有其他任务都更不可预测,但预期的使用率仍然是每秒5-20次(轻量级和中等量级任务),这还取决于网络的繁忙程度。计时器和快速池设计用于执行任何类型的任务,只要执行,预计每秒使用20-50次


非常感谢您的建议。

最好的解决方案是使您的应用程序适应预期的流量。 您可以通过多种方式实现这一点:

  • 使用微服务架构设计它让编排器处理高峰流量
  • 设计一个应用程序,动态读取线程池大小的参数(从数据库、文件、配置服务器……),以便在需要时更改值
  • 如果只需调整应用程序,而不需要动态更改值,请将配置放入文件(或数据库)中。检查不同的配置,以找到最适合您需要的配置
重要的是删除类似于此的代码:

cmdPool = Executors.newFixedThreadPool(3);
并将其替换为类似于此的代码

@Value("${cmdPoolSize}")
private int cmdPoolSize;

...

cmdPool = Executors.newFixedThreadPool(cmdPoolSize);
其中池的大小不是来自代码,而是来自外部配置

更好的方法是使用参数定义池的类型:

@Value("${cmdPoolType}")
private String cmtPoolType;

@Value("${cmdPoolSize}")
private int cmdPoolSize;

...

if (cmdPoolType.equals("cached")) {
  cmdPool = Executors.newCachedThreadPool();
} else if (cmdPoolType.equals("fixed")) {
  cmdPool = Executors.newFixedThreadPool(cmdPoolSize);  
}
选择合理的可用池类型


在最后一种情况下,您还可以使用spring配置文件,并在启动应用程序之前对其进行更改。

最好的解决方案是使您的应用程序适应预期的流量。 您可以通过多种方式实现这一点:

  • 使用微服务架构设计它让编排器处理高峰流量
  • 设计一个应用程序,动态读取线程池大小的参数(从数据库、文件、配置服务器……),以便在需要时更改值
  • 如果只需调整应用程序,而不需要动态更改值,请将配置放入文件(或数据库)中。检查不同的配置,以找到最适合您需要的配置
重要的是删除类似于此的代码:

cmdPool = Executors.newFixedThreadPool(3);
并将其替换为类似于此的代码

@Value("${cmdPoolSize}")
private int cmdPoolSize;

...

cmdPool = Executors.newFixedThreadPool(cmdPoolSize);
其中池的大小不是来自代码,而是来自外部配置

更好的方法是使用参数定义池的类型:

@Value("${cmdPoolType}")
private String cmtPoolType;

@Value("${cmdPoolSize}")
private int cmdPoolSize;

...

if (cmdPoolType.equals("cached")) {
  cmdPool = Executors.newCachedThreadPool();
} else if (cmdPoolType.equals("fixed")) {
  cmdPool = Executors.newFixedThreadPool(cmdPoolSize);  
}
选择合理的可用池类型

在最后一种情况下,您还可以使用spring配置文件,并在启动应用程序之前对其进行更改