线程池
线程池
Executors 封装 线程池(不推荐使用)
直接使用ThreadPoolExecutor ,根据业务需求灵活配置,避免OOM发生的风险。
1 /** 2 * 可缓存线程池 3 * 同时执行的最大线程数是Integer.MAX_VALUE,是高度可伸缩的线程池。可能发生OOM异常。<br/> 4 * 线程空闲时间60秒,工作线程处于空闲状态,可以回收工作线程复用。(threadlocal在线池复用的场景,要注意,容易产生脏数据)<br/> 5 * 如果任务数持续增加,没有可复用的工作线程,将不断的创建新线程处理任务。 6 */ 7 Executors.newCachedThreadPool(); 8 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 9 20L, TimeUnit.MICROSECONDS, 10 new SynchronousQueue<Runnable>(), new MyThreadFactory()); 11 12 13 /** 14 * 固定大小线程池<br/> 15 * newFixedThreadPool核心线程数和同时执行最大线程数相等,并且固定一个数,不存在空闲线程,空闲线程没有任何作用,空闲时间设置为零。<br/> 16 * newSingleThreadExecutor核心线程数和同时执行最大线程数为一,保证FIFO执行所有任务。<br/> 17 * 无界队列(队列最大为Integer.MAX_VALUE),瞬间请求过大,会有OOM风险。 18 * 19 */ 20 Executors.newFixedThreadPool(2, new MyThreadFactory()); 21 Executors.newSingleThreadExecutor(new MyThreadFactory()); 22 threadPoolExecutor = new ThreadPoolExecutor(2, 2, 23 0L, TimeUnit.MILLISECONDS, 24 new LinkedBlockingQueue<Runnable>(), 25 new MyThreadFactory()); 26 27 /** 28 * 周期和定时线程池<br/> 29 * 同时执行的线程最大为Integer.MAX_VALUE 存在OOM风险。可以定时和周期执行任务。 30 * 31 */ 32 Executors.newScheduledThreadPool(2); 33 34 /** 35 * 36 * 并行度线程池<br/> 37 * 38 * 使用多个队列,并行度默认为cpu数量。 39 * 40 * 41 */ 42 Executors.newWorkStealingPool();
ThreadPoolExecutor 构造器参数
1 /** 2 * 线程池<br/> 3 * 线程池ThreadPoolExecutor的参数使用说明<br/> 4 * {@code corePoolSize}核心线程数,一直维持在线程池中,即使他们是空闲的,除非设置了 {@code allowCoreThreadTimeOut}<br/> 5 * <p> 6 * {@code maximumPoolSize}最大线程数,线程池中允许的最大线程数。最大线程数大于等于核心线程数。<br/> 7 * <p> 8 * {@code keepAliveTime} 空闲线程存活时间, 当线程数大于核心线程时,这个时间是空闲线程终止之前等待新的任务的最大时间 。<br/> 9 * <p> 10 * {@code unit} 空闲线程存活时间的单位<br/> 11 * <p> 12 * {@code workQueue} 工作队列,当工作线程大于核心线程时,新的任务加入工作队列中。<br/> 13 * <p> 14 * {@code threadFactory} 线程工厂,线程池通过线程工厂创建新的线程。<br/> 15 * <p> 16 * {@code handle} 拒绝策略,当达到最大线程数也就是达到线程边界和队列容量最大值时,会用到拒绝策略。<br/> 17 */
ThreadPoolExecutor execute执行过程
1 /** 2 * ThreadPoolExecutor execute 3 */ 4 public void execute(Runnable command) { 5 //判空 6 if (command == null) 7 throw new NullPointerException(); 8 //获取执行器计数 9 int c = ctl.get(); 10 //活动线程与核心线程比较,小于侧创建新的线程。 11 if (workerCountOf(c) < corePoolSize) { 12 //添加任务 13 if (addWorker(command, true)) 14 //添加成功退出 15 return; 16 c = ctl.get(); 17 } 18 19 //如果执行器未关闭,添加到队列中 20 if (isRunning(c) && workQueue.offer(command)) { 21 int recheck = ctl.get(); 22 //如果执行器关闭,删除队列 23 if (! isRunning(recheck) && remove(command)) 24 //调用拒绝策略 25 reject(command); 26 //无活动线程,创建新的线程 27 else if (workerCountOf(recheck) == 0) 28 addWorker(null, false); 29 } 30 //无法创建新的任务 31 else if (!addWorker(command, false)) 32 //调用拒绝策略 33 reject(command); 34 }
ThreadPoolExecutor RejectedExecutionHandler 拒绝策略
根据业务需求选择合适的拒绝策略,如果ThreadPoolExecutor自带的四种拒绝策略无法满足需求,也可以实现RejectedExecutionHandler接口自定义拒绝策略。
1 public static class CallerRunsPolicy implements RejectedExecutionHandler { 2 public CallerRunsPolicy() { 3 } 4 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 5 //执行器没有关闭,则直接调用任务的run方法。 6 if (!e.isShutdown()) { 7 r.run(); 8 } 9 //执行器关闭,抛弃任务。 10 } 11 } 12 public static class AbortPolicy implements RejectedExecutionHandler { 13 public AbortPolicy() { 14 } 15 /** 16 * 直接抛出RejectedExecutionException这个异常。 17 */ 18 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 19 throw new RejectedExecutionException("Task " + r.toString() + 20 " rejected from " + 21 e.toString()); 22 } 23 } 24 public static class DiscardPolicy implements RejectedExecutionHandler { 25 public DiscardPolicy() { 26 } 27 /** 28 * 什么也不做直接抛弃任务 29 */ 30 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 31 } 32 } 33 public static class DiscardOldestPolicy implements RejectedExecutionHandler { 34 public DiscardOldestPolicy() { 35 } 36 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 37 //线程执行器未关闭 38 if (!e.isShutdown()) { 39 //删除队列最老的任务 40 e.getQueue().poll(); 41 //把任务交给执行器执行。 42 e.execute(r); 43 } 44 //线程执行器关闭,直接抛弃任务。 45 } 46 }
posted on 2019-12-30 11:38 seesea_bky 阅读(142) 评论(0) 收藏 举报
浙公网安备 33010602011771号