一、架构说明:
二、为什么使用线程池,优势是什么?
线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,那么超出数量的线程排队等候,等其它线程执行完毕,再从队列中取出任务来执行。
特点:线程复用、控制最大并发数量、管理线程
优点:
2、特点:
newFixedThreadPool():执行长期任务,性能好很多
newSingleThreadExecutor():一个任务一个任务顺序执行
newCachedThreadPool():是一种用来处理大量短时间工作任务的线程池
代码演示:
public class MyThreadPoolDemo { public static void main(String[] args) { // ExecutorService executorService = Executors.newFixedThreadPool(5); //一次有5个处理线程 // ExecutorService executorService = Executors.newSingleThreadExecutor(); // ExecutorService executorService = Executors.newCachedThreadPool(); //真实项目中使用 ExecutorService executorService = new ThreadPoolExecutor(2, 3, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy()); try { //模拟10个用户来办理业务 for (int i = 0; i < 12; i++) { // try { // TimeUnit.SECONDS.sleep(1); // } catch (InterruptedException e) { // e.printStackTrace(); // } executorService.execute(() -> { System.out.println(Thread.currentThread().getName()+" 办理业务"); }); } } catch (Exception e) { e.printStackTrace(); }finally { executorService.shutdown(); } } }
三、ThreadPoolExecutor
四、线程池七大参数介绍
corePoolSize:线程池的核心线程数
maximumPoolSize:线程池的最大线程数,此值必须大于等于1
keepAliveTime:多余的空闲线程的存活时间,线程池数量超过corePoolSize,空闲时间达到keepAliveTime值时,多余空闲线程会被销毁直到剩下corePoolSize个线程为止
TimeUnit:keepAliveTime的单位
workQueue:任务队列,被提交但是尚未被执行的任务
threadFactory:设置创建线程的工厂
RejectedExecutionHandler:拒绝策略,当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler 来处理
五、线程池底层工作原理
1、在创建了线程池后,等待提交过来的任务请求。
2、ThreadPoolExecutor执行execute方法,线程池会做如下判断:
3、当一个线程完成任务,会从队列中取下一个任务来执行
4、当线程空闲时间达到keepAliveTime值时,线程池会判断,如果当前线程数大于corePoolSize,那么这个线程就会被停掉。
所以线程池的所有任务完成后最终会收缩到corePoolSize的大小。
六、线程池的4种拒绝策略
当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务
六、工作中线程池实际使用
public class ThreadPoolExecutorDemo { public static void main(String[] args) { ExecutorService executorService = new ThreadPoolExecutor(2, 3, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy()); } }
六、线程池配置合理线程数
查看电脑cpu核数:
public class CPUCoresDemo { public static void main(String[] args) { System.out.println(Runtime.getRuntime().availableProcessors()); } }
1、CPU密集型:任务需要大量的运算,而没有阻塞,CPU一直全速运行。
CPU密集型任务配置尽可能的少的线程数量,
公式:CPU核数 + 1个线程的线程池。
2、IO密集型:任务需要大量的IO,即大量的阻塞
由于IO密集型任务线程并不是一直在执行任务,可以多分配一点线程数,如 CPU * 2 。
使用公式:CPU 核数/(1-阻塞系数);其中阻塞系数在 0.8 ~ 0.9 之间。
java面试-线程池使用过吗,谈谈对ThreadPoolExector的理解
原文:https://www.cnblogs.com/wjh123/p/11192656.html