如何进行线程池配置与数据库连接池最大连接数配置,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
线程池 相关配置,不仅平时经常用到,而且面试也会经常问到。
CPU 密集型任务:这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。
I/O 密集型任务:这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是 2N。
综上可知:当线程数量太小,同一时间大量请求将被阻塞在线程队列中排队等待执行线程,此时 CPU 没有得到充分利用;当线程数量太大,被创建的执行线程同时在争取 CPU 资源,又会导致大量的上下文切换,从而增加线程的执行时间,影响了整体执行效率。通过测试可知,4~6 个线程数是最合适的。
public ThreadPoolExecutor(int corePoolSize,//线程池的核心线程数量
int maximumPoolSize,//线程池的最大线程数
long keepAliveTime,//当线程数大于核心线程数时,多余的空闲线程存活的最长时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列,用来储存等待执行任务的队列
ThreadFactory threadFactory,//线程工厂,用来创建线程,一般默认即可
RejectedExecutionHandler handler) //拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务
但是某些号称XXX架构师配置线程池参数(或者jdbc连接池数量)还是会拍脑袋,随便定个 核心线程数或者最大线程数100
这就是没有性能意思的码农(估计都了解过怎么配置,就是没有在意)了。 虽然说配置比如 最大线程数100 , 其实对于并发量不大的项目来说,其实运行起来也不会出什么问题。但是 能改则改。
// CPU 核心数:// 核数 。 CPU 密集计算: N+1// IO 类型的就是: 2Nint cores = Runtime.getRuntime().availableProcessors();
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 自定义异步线程的执行器
* 使用 ThreadPoolTaskExecutor 线程池方式,避免开启过多的线程
*
* @author James
* @date 2018/7/16 上午11:40
*/
@Configuration
@EnableAsync
public class ExecutorConfig
{
/**
* Set the ThreadPoolExecutor's core pool size.
*/
private int corePoolSize = 4;
/**
* Set the ThreadPoolExecutor's maximum pool size.
*/
private int maxPoolSize = Runtime.getRuntime().availableProcessors() + 3;
/**
* Set the capacity for the ThreadPoolExecutor's BlockingQueue.
* 队列数不能太大,否则就会任务堆积,处理就太慢了。
*/
private int queueCapacity = 300;
@Bean
public Executor myAsync()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("MyExecutor-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 。 一般这种任务不能丢弃
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
以上代码就是 当spring boot 中 执行 异步 代码的时候所用到的线程池配置了: 即加了 @Async 的方法
使用 LinkedBlockingQueue 是因为其可以有更高的吞吐量
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.concurrent.*;
@Component
public class ExecutionResultPool {
private static final Logger logger = LoggerFactory.getLogger(ExecutionResultPool.class);
private ExecutorService threadPool;
public void init() {
// 核数 。 CPU 密集计算: N+1
// IO 类型的就是: 2N
int cores = Runtime.getRuntime().availableProcessors();
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("timing-executor-pool-%d").build();
threadPool = new ThreadPoolExecutor(4,
cores+3, 30, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
threadFactory,
(r, executor) -> {
try {
// // 尝试再次加入队列。如果队列已满,那么等待,直到队列空了就放进去
executor.getQueue().put(r);
} catch (InterruptedException e) {
logger.error("任务加入队列失败", e);
Thread.currentThread().interrupt();
}
});
logger.info("初始化任务执行线程池 {}", threadFactory);
}
public void execute(Runnable runnable) {
threadPool.execute(runnable);
}
}
关于如何进行线程池配置与数据库连接池最大连接数配置问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
亿速云「云数据库 MySQL」免部署即开即用,比自行安装部署数据库高出1倍以上的性能,双节点冗余防止单节点故障,数据自动定期备份随时恢复。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/ouminzy/blog/4535161