七大参数: public ThreadPoolExecutor(int corePoolSize,// 核心线程数 int maximumPoolSize,//最大线程数 long keepAliveTime,// 除核心线程外,线程保持活跃时间 TimeUnit unit,//时间单位 BlockingQueue<Runnable> workQueue,//阻塞队列 ThreadFactory threadFactory,//线程工厂类,默认 RejectedExecutionHandler handler) //线程处理策略
ExecutorService executorService = new ThreadPoolExecutor( 2, 3, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
参数剖析:
两个核心线程,当等待队列超过核心线程+阻塞队列时,会开启最大线程,当任务结束时,不存在阻塞现象,最大线程根据线程存活时间,关闭最大线程。
三大方法:
手动创建线程池一般使用原生的new ThreadPoolExecutor。避免使用
// newSingleThreadExecutor() 单例线程 //ExecutorService executorService = Executors.newSingleThreadExecutor(); // newFixedThreadPool() 固定个数线程 // ExecutorService executorService = Executors.newFixedThreadPool(3); // 可变动线程 0 ~ 最大默认值 //ExecutorService executorService = Executors.newCachedThreadPool();
三种方式创建线程。尤其是第三种,如果不设置线程最大个数,可能会导致OOM。
四大策略:
线程池最大线程数:最大线程数+阻塞队列
new ThreadPoolExecutor.AbortPolicy() // 超出最大线程数,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() // 调用线程执行,谁调用谁执行
new ThreadPoolExecutor.DiscardPolicy() // 丢弃,打出,放置 策略
new ThreadPoolExecutor.DiscardOldestPolicy() // 丢弃最旧的线程,把新的队列线程加入进去
如何设置最大线程数:
CPU密集型: 线程执行时,执行大量的业务运算和逻辑,对数据库操作少
最大线程数:CPU个数
获取的是cpu核心线程数:Runtime.getRuntime().availableProcessors()
IO密集型:线程执行,业务逻辑简单,频繁操作数据库
最大线程数:CPU个数 *2