手动创建线程池方法及参数
//手动创建线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor(2,5, 3,TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new ThreadPoolExecutor.AbortPolicy());public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); }
一、线程池构造方法的参数
二、添加线程的规则
三、任务存储工作队列
四、手动创建线程池
1.newFixedThreadPool 固定线程池(核心线程数=最大线程数,队列满后无法增加线程)
ExecutorService executorService = Executors.newFixedThreadPool(5);public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); } 创建一个线程池,指定线程数量5,默认使用无界队列LinkedBlockingQueue,大量任务执行未完成的情况下,可能会造成OOM内存溢出异常。
2.newSingleThreadExecutor 单一线程池
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); } 与newFixedThreadPool类似,只是线程数量固定为1,同样使用无界队列,大量任务同样造成OOM内存溢出正常。
3.newCachedThreadPool 可缓存线程池(可自动回收空闲线程,队列没有容量)
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); } 无界线程数量,直接交换队列,线程存活默认60s自动回收,可能会创建数量特别多的线程导致OOM内存溢出异常。
4.newScheduledThreadPool 定时线程池(周期性任务执行,使用延迟队列DelayedWorkQueue)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }如:
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(10); //10s后开始执行一次任务,需手动关闭 threadPool.schedule(new Task(),10, TimeUnit.SECONDS); //第一次1s后执行,后面每3s执行一次 threadPool.scheduleAtFixedRate(new Task(),1,3,TimeUnit.SECONDS);
五、线程池线程数量设置多少合适(最佳:不同程序做不同的压测得出最优线程数量)
六、停止线程池的正确方法
1.shutdown 存量任务和当前任务执行完毕后线程关闭,不再接收新任务
2.isShutdown获取当前线程池的开启关闭状态
3.isTerminated获取线程池是否真正已停止
4.awaitTermination监测时间范围内线程是否运行完毕
5.shutdownNow 立刻停止线程
七、线程池的暂停和恢复
钩子函数beforeExecute
八、 线程池的实现原理,源码分析
线程池的组成部分:线程池管理器、工作线程、任务队列、任务接口(Task)
runWorker只要Runnable任务不为空就会一直执行
九、线程池任务的拒绝策略
拒绝策略提供顶级接口 RejectedExecutionHandler ,其中方法 rejectedExecution 即定制具体的拒绝策略的执行逻辑。
jdk默认提供了四种拒绝策略:
- AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行
- CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
- DiscardPolicy - 直接丢弃,其他啥都没有
- DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入
十、线程池状态和使用注意
注意:
手动创建线程池,避免风险;线程数设置合理;考虑多个线程池间的影响