【易客吧】_全网激活码总代_激活码商城

您现在的位置是:首页 > 热门资讯 > 正文

热门资讯

Spring 线程池扩展指南:自定义配置、队列策略和拒绝策略 (springernature)

用户投稿2024-04-17热门资讯24
Spring 线程池扩展指南:自定义配置、队列策略和拒绝策略Spring Framework 提供了一个内置的线程池抽象,允许开发者轻松配置和管理线程池。在某些情况下,需要对线程池进行更高级的自定义以满足特定的应用程序要求。本文提供了一个分步指南,说明如何扩展 Spring 线程池以配置自定义队列和拒绝策略。定制配置Spring 线程池可以通过 `@EnableAsync` 注解和 `ThreadPoolTaskExecutor` Bean 来配置。`ThreadPoolTaskExecutor` 类提供了一个丰富的配置选项列表,允许开发者调整线程池的各种参数,例如核心线程数、最大线程数和队列容量。要在 Spring 中自定义线程池配置,请按照以下步骤操作:1. 在 Spring 配置类中,使用 `@EnableAsync` 注解启用异步支持。 2. 使用 `ThreadPoolTaskExecutor` 实例创建 Bean。 3. 配置线程池参数,例如 `corePoolSize`、`maxPoolSize` 和 `queueCapacity`。下面是一个示例配置: java @EnableAsync @Configuration public class ThreadPoolConfiguration {@Bean public TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(50);return executor;} }自定义队列策略Spring 线程池支持多种队列实现,包括 `LinkedBlockingQueue`、`ArrayBlockingQueue` 和 `PriorityBlockingQueue`。默认情况下,Spring 使用 `LinkedBlockingQueue`,它是一个无界的队列,在任务队列已满时会阻塞提交任务的线程。要自定义队列策略,需要指定一个实现 `BlockingQueue` 接口的自定义队列类。例如,要使用有界的队列,可以实现一个 `BoundedBlockingQueue` 类: java public class BoundedBlockingQueue implements BlockingQueue {private final Queue queue;private final int capacity;public BoundedBlockingQueue(int capacity) {this.queue = new ArrayBlockingQueue<>(capacity);this.capacity = capacity;}// ... 省略其他实现 }可以在线程池配置中指定自定义队列: java @EnableAsync @Configuration public class ThreadPoolConfiguration {@Beanpublic TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(50);executor.setQueue(new BoundedBlockingQueue<>(50));return executor;} }自定义拒绝策略当任务队列已满且无法添加新任务时,Spring 线程池会应用拒绝策略。默认情况下,Spring 使用 `AbortPolicy`,它会抛出 `RejectedExecutionException`。要自定义拒绝策略,需要指定一个实现 `RejectedExecutionHandler` 接口的自定义拒绝策略类。例如,要创建一个拒绝策略,该策略将拒绝的任务添加到另一个队列中,可以实现一个 `AlternateQueueRejectionHandler` 类: java public class AlternateQueueRejectionHandler implements RejectedExecutionHandler {private final BlockingQueue alternateQueue;public AlternateQueueRejectionHandler(BlockingQueue alternateQueue) {this.alternateQueue = alternateQueue;}@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {try {alternateQueue.put(r);} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RejectedExecutionException("Task rejected", e);}} }可以在线程池配置中指定自定义拒绝策略: java @EnableAsync @Configuration public class ThreadPoolConfiguration {@Beanpublic TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(50);executor.setRejectedExecutionHandler(new AlternateQueueRejectionHandler(alternateQueue));return executor;} }结论通过自定义配置、队列策略和拒绝策略,可以灵活地调整 Spring 线程池的行为以满足应用程序特定的要求。这些扩展允许开发者对线程池进行更精细的控制,从而优化并发应用程序的性能和可靠性。

SpringBoot使用线程池

线程池是一种线程使用模式。 线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。 线程池维护多个线程,等待监督管理者分配可并发执行的任务。 这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。 使用线程池,有几点好处: Java开发,我们使用JDK环境,开发框架基本都是Spring全家桶。 线程池的基础原理都在JDK中,JDK1.5新增线程池相关类,在核心jar包 中, 下面。 看一下jdk中线程池继承关系类图:JDK中,使用 ThreadPoolExecutor 给创建了几个不同功能种类的线程池,可以调出来看看: 看一下都有什么特点: 从上面可以看出他们各有各的特点,但是阿里巴巴开发守则却不推荐使用以上线程池,因为它们可能会对服务资源的浪费,所以推荐使用通过ThreadPoolExecutor自定线程池。 Spring中将Java中的线程池进行了封装,而且提供了默认实现,也能自定义线程池,我一般都用Spring中的线程池包。 Spring中的线程池和JDK中的基本一样,在 包下面。 和JDK中对应的,Spring的顶层接口是 TaskExecutor ,它实现了JDK中的 Executor 接口。 Spring中常用的线程池是 ThreadPoolTaskExecutor ,它是是借助于JDK并发包中的 来实现的。 要想使用线程池,先了解一下线程池中的一些参数: 因为我们常用的是 ThreadPoolExecutor 线程池,所以去这个类中找。 上面配置了线程池,并生成了线程池bean,交给了Spring容器管理,使用时注入即可使用。 SpringBoot线程池自动装配在 spring-boot-autoconfigure 这个jar中,在 类中。 自动装配条件:当往线程池中提交新任务时,线程池主要流程如下:核心线程数 -> 线程队列 -> 最大线程数 -> 拒绝策略 所以使用线程池,需要注意:

SpringBoot如何整合Hystrix

在配置文件中加入如下配置:

将全局的默认超时时间由1s修改为3s,但是配置未起作用。

Archaius 默认支持两种方式来加载本地的配置文件:

使用注解的方式,为方法添加hystrix断路器。

在resources\中进行配置:

使用Hystrix后,配置均会在#AbstractCommand 类中组装。

[图片上传失败...(image-a9070e-77)]

注:需要注意的是,虽然在3个地方设置了 超时时间。但是只有4000ms的超时时间生效。

1. hystrix配置的优先级是怎么样的呢? 2. 如何为某个方法配置不同的hystrix策略?

优先级从低到高的配置:

注:全局配置是default的配置,而实例配置为commandKey配置。

默认情况下,Hystrix会使用 类名作为CommandGroup ,会使用 方法名作为CommandKey。 可以使用commandKey进行个性化的配置。参考【1.3 如何使用】

[图片上传失败...(image-95f991-77)]

表示()的执行时的策略,有以下两种策略:

Spring 线程池扩展指南:自定义配置、队列策略和拒绝策略 (springernature) 第1张

以下属性控制() 如何执行,这些属性对隔离策略THREAD 和SEMAPHORE 都起作用。

此属性设置从调用线程允许()方法允许的最大并发请求数,如果达到最大的并发量,则接下来的请求都会被拒绝并且抛出异常。

控制断路器的行为。

默认值20。若是在10s(窗口时间)内,只收到19个请求且都失败了,则断路器也不会开启。

断路器跳闸后,在此值的时间内,hystrix会拒绝新的请求,只有过了这个时间,断路器才会打开闸门。默认值5000ms

设置失败百分比的阈值,如果失败比率超过这个值,则断路器跳闸并且进入fallback状态。默认值:50

如果这个属性true强制断路器进入开路(跳闸)状态,它将拒绝所有请求。 此属性优先于。默认值false

如果设置true,则强制使断路器进行关闭状态,此时会允许执行所有请求,无论是否失败的次数达到值。默认值:false。

捕获和HystrixCommand以及HystrixObservableCommand执行信息相关的配置属性。

Hystrix保留断路器使用和发布指标的时间。默认值

% == 01 如/10、/20是正确的配置,但是/7错误的。默认值:10 注:在高并发的环境里,每个桶的时间长度建议大于100ms。

该属性控制HystrixCommand使用到的Hystrix的上下文。

默认值:true

表示是否开启日志,打印执行HystrixCommand的情况和事件。默认值true

设置请求合并请求。

默认值_VALUE

默认值:10

是否对() 和 ()开启请求缓存 默认值:true

默认值:10

在1.5.9中添加。此属性设置最大线程池大小。这是在不开始拒绝HystrixCommands的情况下可以支持的最大并发数量。请注意,此设置仅在您设置时生效allowMaximumSizeToDivergeFromCoreSize。在1.5.9之前,核心和最大尺寸始终相等。 默认值:10

设置最大的BlockingQueue队列的值。如果设置-1,则使用SynchronousQueue队列(无限队列)。如果设置正数,则使用LinkedBlockingQueue队列。默认值:-1

因为maxQueueSize值不能被动态修改,所有通过设置此值可以实现动态修改等待队列长度。即等待的队列的数量大于queueSizeRejectionThreshold时(但是没有达到maxQueueSize值),则开始拒绝后续的请求进入队列。 默认值:5注:如果设置-1,则属性不启作用。

设置线程空闲多长时间后,释放(maximumSize-coreSize )个线程。默认值1(分钟)

设置allowMaximumSizeToDivergeFromCoreSize值为true时,maximumSize才有作用 默认值:false

官网——Hystrix的参数配置 Hystrix常用功能介绍 Hystrix源码解析--从原生的lib开始使用hystrix(一)

线程池工作原理

管理线程,当线程执行完当前任务,不会死掉而是 会从队列里面取 1.降低系统资源消耗。 通过复用已存在的线程,降低线程创建和销毁造成的消耗; 2.提高响应速度。 当有任务到达时,无需等待新线程的创建便能立即执行; 3.提高线程的可管理性。 线程是稀缺资源,如果无限制的创建,不仅会消耗大量系统资源,还会降低系统的稳定性,使用线程池可以进行对线程进行统一的分配、调优和监控。 本文主要是围绕 ThreadPoolExecutor(线程池框架的核心类)的构造方法参数 展开 线程池中的核心线程数。 当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行。 额外最大线程数。 上面说到任务数足够多,且使用的是有界队列,如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,首先从队列里面取,如果队列里面的消息执行完毕,等下一定时间,额外线程自动销毁。 线程空闲时的存活时间。 默认情况下,可以理解成额外最大线程数没活干了,额外线程线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。 但是如果调用了allowCoreThreadTimeOut(boolean)方法,keepAliveTime参数也会起作用,直到线程池中的线程数为0。 keepAliveTime参数的时间单位。 任务缓存队列,用来存放等待执行的任务。 如果当前线程数为corePoolSize,继续提交的任务就会被保存到任务缓存队列中,等待被执行。 一般来说,这里的BlockingQueue有以下三种选择: * SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态。 因此,如果线程池中始终没有空闲线程(任务提交的平均速度快于被处理的速度),可能出现无限制的线程增长。 * LinkedBlockingQueue:基于链表结构的阻塞队列,如果不设置初始化容量,其容量为_VALUE,即为无界队列。 因此,如果线程池中线程数达到了corePoolSize,且始终没有空闲线程(任务提交的平均速度快于被处理的速度),任务缓存队列可能出现无限制的增长。 * ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务。 线程工厂,创建新线程时使用的线程工厂。 任务拒绝策略,当阻塞队列满了,且线程池中的线程数达到maximumPoolSize,如果继续提交任务,就会采取任务拒绝策略处理该任务,线程池提供了4种任务拒绝策略:*AbortPolicy :丢弃任务并抛出RejectedExecutionException异常,默认策略;*CallerRunsPolicy :由调用execute方法的线程执行该任务; *DiscardPolicy :丢弃任务,但是不抛出异常; *DiscardOldestPolicy :丢弃阻塞队列最前面的任务,然后重新尝试执行任务(重复此过程)。 * 当然也可以根据应用场景实现 RejectedExecutionHandler 接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。 总结下上诉参数:假设corePoolSize为10 ,maximumPoolSize为10,线程空闲时的存活时间为60s,队列采用的是有界队列ArrayBlockingQueue 设置阈值200,使 用拒绝策略 , 当前2000个任务提交过来 流程如下图 参数案例描述: 当前2000笔 任务进来,10个核心线程去处理,剩下的1990任务队列里面放200个。 剩下的1790个任务。 队列塞满会去创建10个额外线程和核心线程一起去 去执行剩下的1780个任务。 当还有剩下任务处理不了就会触发任务拒绝策略 。 当前220笔 任务进来,10个核心线程去处理,剩下的210任务队列里面放200个。 剩下的10个任务。 队列塞满会去创建10个额外线程 去执行队列放不下的任务。 当额外线程和核心线程处理完队列里面的队列。 没有任务可执行时,额外线程会等待我们设置的keepAliveTime,还是没有任务的情况下,就会被回收了 。 以上是绝对理想的状况下。 由参数可知 核心线程 和额外线程值是相同的,额外线程被回收时间是0,采用的是无界队列。 默认采用的拒绝策略为 AbortPolicy。 分析得 核心线程和额外线程处理不过来得情况,会一直往队列里面放任务。 可能存在的问题:队列过大 导致内存溢出 OOM 当任务量足够大,超过队列。 交由额外线程处理。 就会创建过多线程。 可能存在问题:特殊场景下,线程过多可能会导致系统奔溃。 cpu负载过高。 1.具体解决方案 根据业务系统而定: 华瑞批量查证举例:定时任务CZJZRW001每隔2min 轮询一次 会从业务表verifycationTask 中 查询出待处理和处理中的状态的任务 根据表中的查证类型 分流到具体的 反欺诈异步查证 ,还款查证,充值查证,贷款查证 。 具体查证根据处理结果更新verifycationTask表查证状态。 处理成功 或者失败的定时任务无法再次轮询。 这样就不需要考虑以上场景。 使用线程池的情况下核心线程,额外线程处理不过来且队列已满使用DiscardPolicy拒绝不抛异常策略,即可满足该业务场景。 类结构如下图2.思路 可以实现 RejectedExecutionHandler接口 自定义拒绝策略 将被拒绝的任务信息缓存到磁盘,等待线程池负载较低 从磁盘读取重新提交到任务里面去执行

若对本页面资源感兴趣,请点击下方或右方图片,注册登录后

搜索本页相关的【资源名】【软件名】【功能词】或有关的关键词,即可找到您想要的资源

如有其他疑问,请咨询右下角【在线客服】,谢谢支持!

Spring 线程池扩展指南:自定义配置、队列策略和拒绝策略 (springernature) 第2张

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~
欢迎你第一次访问网站!