目前为止,通过v1版本的MyThreadPoolExecutor源码,已经将jdk线程池ThreadPoolExecutor在RUNNING状态下提交任务 , 启动工作线程执行任务相关的核心逻辑讲解完毕了(不考虑优雅停止) 。
jdk线程池默认支持的四种拒绝策略jdk线程池支持用户传入自定义的拒绝策略处理器,只需要传入实现了RejectedExecutionHandler接口的对象就行 。而jdk在ThreadPoolExecutor中提供了默认的四种拒绝策略方便用户使用 。
- AbortPolicy拒绝接受任务时会抛出RejectedExecutionException,能让提交任务的一方感知到异常的策略 。适用于大多数场景 , 也是jdk默认的拒绝策略 。
- DiscardPolicy直接丢弃任务的拒绝策略 。简单的直接丢弃任务,适用于对任务执行成功率要求不高的场合
- DiscardOldestPolicy丢弃当前工作队列中最早入队的任务,然后将当前任务重新提交 。适用于后出现的任务能够完全代替之前任务的场合(追求最终一致性)
- CallerRunsPolicy令调用者线程自己执行所提交任务的拒绝策略 。在线程池压力过大时,让提交任务的线程自己执行该任务(异步变同步),能有效地降低线程池的压力 , 也不会丢失任务,但可能导致整体业务吞吐量大幅降低 。
/*** 默认的拒绝策略:AbortPolicy* */private static final MyRejectedExecutionHandler defaultHandler = new MyAbortPolicy();/*** 抛出RejectedExecutionException的拒绝策略* 评价:能让提交任务的一方感知到异常的策略,比较通用,也是jdk默认的拒绝策略* */public static class MyAbortPolicy implements MyRejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable command, MyThreadPoolExecutor executor) {// 直接抛出异常throw new RejectedExecutionException("Task " + command.toString() +" rejected from " + executor.toString());}}/*** 令调用者线程自己执行command任务的拒绝策略* 评价:在线程池压力过大时 , 让提交任务的线程自己执行该任务(异步变同步),*能够有效地降低线程池的压力,也不会丢失任务,但可能导致整体业务吞吐量大幅降低* */public static class MyCallerRunsPolicy implements MyRejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable command, MyThreadPoolExecutor executor) {if (!executor.isShutdown()) {// 如果当前线程池不是shutdown状态,则令调用者线程自己执行command任务command.run();}else{// 如果已经是shutdown状态了,就什么也不做直接丢弃任务}}}/*** 直接丢弃任务的拒绝策略* 评价:简单的直接丢弃任务,适用于对任务执行成功率要求不高的场合* */public static class MyDiscardPolicy implements MyRejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable command, MyThreadPoolExecutor executor) {// 什么也不做的,直接返回// 效果就是command任务被无声无息的丢弃了,没有异常}}/*** 丢弃当前工作队列中最早入队的任务,然后将当前任务重新提交* 评价:适用于后出现的任务能够完全代替之前任务的场合(追求最终一致性)* */public static class MyDiscardOldestPolicy implements MyRejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable command, MyThreadPoolExecutor executor) {if (!executor.isShutdown()) {// 如果当前线程池不是shutdown状态,则丢弃当前工作队列中最早入队的任务,然后将当前任务重新提交executor.getQueue().poll();executor.execute(command);}else{// 如果已经是shutdown状态了,就什么也不做直接丢弃任务}}}
jdk默认的四种线程池实现jdk中除了提供了默认的拒绝策略 , 还在Executors类中提供了四种基于ThreadPoolExecutor的、比较常用的线程池,以简化用户对线程池的使用 。这四种线程池可以通过Executors提供的public方法来分别创建:newFixedThreadPoolnewFixedThreadPool方法创建一个工作线程数量固定的线程池,其创建ThreadPoolExecutor时传入的核心线程数corePoolSize和最大线程数maximumPoolSize是相等的 。因此其工作队列传入是一个无界的LinkedBlockingQueue,无界的工作队列意味着永远都不会创建新的非核心线程 。在默认allowCoreThreadTimeOut为false的情况下,线程池中的所有线程都是不会因为idle超时而销毁的核心线程 。适用场景:由于工作线程数量固定,“fixedThreadPool”适用于任务流量较为稳定的场景
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 我的Vue之旅 10 Gin重写后端、实现页面详情页 Mysql + Golang + Gin
- zk系列三:zookeeper实战之分布式锁实现
- 【深入浅出 Yarn 架构与实现】2-2 Yarn 基础库 - 底层通信库 RPC
- OPPO手机怎么才能设置到自己心仪的彩铃
- 手机动态彩铃是怎么设置的(自己手机的彩铃能设置吗)
- 第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料
- 【深入浅出 Yarn 架构与实现】2-1 Yarn 基础库概述
- Golang 实现时间戳和时间的转化
- 二叉搜索树 - C++ 实现
- 【深入浅出 Yarn 架构与实现】1-2 搭建 Hadoop 源码阅读环境