线程池问题

1.线程池七个参数

注意,线程池刚创建时没有线程,任务来了才开始创建线程,或者调用prestartCoreThread()/prestartAllCoreThreads() 创建好核心线程。

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

//参数一:指定线程池的线程数量(核心线程):corePoolSize不能小于0
//参数二:指定线程池可以支持的最大线程数:maximumPoolSize,最大线程数>核心线程数量
//参数三:指定临时线程的最大存活时间:keepAliveTime 不能小于0
//参数四:指定存活时间的单位(秒、分、时、天):unit 时间单位
//参数五:指定任务队列:workQueue 不为null
//参数六:指定用哪个线程工厂创建线程:threadFactory 不为null
//参数七:指定线程,任务满的时候,新任务来了怎么办:threadFactory 不为null

2.Executors提供的四种线程池

3.为什么要使用线程池

  • 线程池的主要工作是控制线程数量,使用线程池可以降低资源消耗、提高响应速率提高线程的可管理性。

4.阻塞队列的作用是什么?为什么是先添加队列而不是先创建最大线程

  • 阻塞队列可以保证阻塞队列没有任务时阻塞获取任务的线程,使线程进入wait状态,释放cpu资源。
    另外,阻塞队列自带阻塞和唤醒功能,当没有任务时,线程池使用阻塞队列的take()挂起,维持核心线程的存活,不至于一直占用cpu。
  • 先添加队列是因为在创建线程时需要获取全局锁,这时候其他线程就会阻塞,影响整体效率。所以将创建最大线程放到后面,阻塞队列可以分担一些任务,减少线程创建造成的效率损失。

5.线程复用原理

线程池将线程和任务解耦,线程是线程,任务是任务,摆脱了之气那thread线程需要对应一个任务的限制。在线程池中,同一个线程可以不断的从任务队列中获取任务,其核心在于线程池将Thread进行了封装,并不是每次执行任务都会调用Thread.start()来创建线程,而是让每个线程去执行循环任务,不停检查是否有任务需要执行,如果有则直接执行,也就是调用任务中的run()方法,将run()方法当成一个普通方法执行,通过这种方式只使固定线程就可以将所有的run()方法串联起来。

6.核心线程数和最大线程数怎么设置

线程数设置和CPU的核数是相关的,不同类型的任务,设置的方式不同。线程池执行的任务分为三种情况:
1)CPU密集型任务:存在大量的计算。核心线程数=CPU核数+1,最大线程数=CPU数量+1。(CPU核数和CPU数量是不同的)。CPU密集型任务主要是执行计算任务,响应时间很快,cpu 一直在运行,这种任务 cpu的利用率很高,那么线程数的配置应该根据 CPU 核心数来决定,CPU 核心数=最大同时执行线程数,加入 CPU 核心数为 4,那么服务器最多能同时执行 4 个线程。过多的线程会导致上下文切换反而使得效率降低。
2)IO密集型任务:主要是IO操作,如文件IO和网络IO。核心线程数=CPU核数2,最大线程数=CPU数量2+1。
执行IO操作是比较耗时的,当某些线程在阻塞时,其对应的CPU就可以去执行其他的线程,通常核心数是CPU核数的2倍。但也不是绝对的,因为有可能这2倍的线程全被阻塞。当然下面的计算公式更为合适:核心线程数=CPU核数*(1+线程等待时间(也叫阻塞时间) / 线程运行总时间)。
3)复合型任务

posted @   一个苦逼的23届毕业生  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示