当前位置: 首页 > wzjs >正文

做宣传可以在哪些网站上发布本周新闻热点事件

做宣传可以在哪些网站上发布,本周新闻热点事件,郴州网红打卡地有哪些,免费分销系统一键生成目录 前言一、Springboot项目如何开启异步?二、存在的问题三、自定义线程池四、自定义线程池使用五、阻塞队列和拒绝策略 前言 当开发中遇到不影响主流程任务时,使用异步去处理。 如有以下场景: 1、业务需要生成一个季度的数据进行员工排名&…

目录

  • 前言
  • 一、Springboot项目如何开启异步?
  • 二、存在的问题
  • 三、自定义线程池
  • 四、自定义线程池使用
  • 五、阻塞队列和拒绝策略


前言

当开发中遇到不影响主流程任务时,使用异步去处理。
如有以下场景:
1、业务需要生成一个季度的数据进行员工排名(涉及到的数据很多),数据查询、组装、按规则排名耗时比较长,并且开发方案能接受延时查看具体排名信息数据。在数据变动时,需要调用重新排名的方法,故把排名方法设置为异步。


一、Springboot项目如何开启异步?

启动类 上添加或者 自定义线程池 上添加注解:@EnableAsync。
执行方法上加上注解 @Async。

启动类配置
在这里插入图片描述
Controller
在这里插入图片描述

Service
在这里插入图片描述
打印信息
在这里插入图片描述
到这里就可以正常使用异步了。

二、存在的问题

虽然在 Spring 框架中,@Async 注解可以用于异步执行方法。

但是Spring 会自动创建一个默认的线程池用于执行方法。这个默认线程池是由 SimpleAsyncTaskExecutor 管理的,它为每个任务创建一个新的线程。虽然这可以工作,但可能会遇到以下问题:

  1. 无限制的线程创建:SimpleAsyncTaskExecutor 会为每个任务创建一个新的线程,而没有最大线程数的限制。如果异步任务的数量非常多,这可能导致大量的线程被创建,消耗大量的系统资源,最终可能导致 OutOfMemoryError 或降低系统性能。
  2. 线程管理:由于每次调用都会创建新线程,没有线程复用,这可能会导致线程管理上的开销,尤其是在高并发场景下。
  3. 调试和监控困难:默认线程池创建的线程名称没有明确的命名规则,这可能会使得在日志中或监控工具中跟踪异步任务变得困难。
  4. 资源竞争:大量的线程可能会引起CPU和内存资源的激烈竞争,尤其是在JVM和操作系统层面上的上下文切换。
  5. 安全性问题:如果异步任务执行的时间过长,而默认线程池没有适当的管理策略,可能会因为线程过多而影响到系统的稳定性和安全性。

三、自定义线程池

鉴于以上问题,建议使用自定义线程池。

import cn.hutool.core.thread.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;/*** 全局异步任务配置类*/
@Slf4j
@EnableAsync
@Configuration
public class GlobalAsyncConfig implements AsyncConfigurer {// 从 application.yml 中注入配置参数@Value("${async.executor.core-pool-size:10}")private int corePoolSize;@Value("${async.executor.max-pool-size:50}")private int maxPoolSize;@Value("${async.executor.keep-alive-seconds:60}")private int keepAliveSeconds;@Value("${async.executor.queue-capacity:200}")private int queueCapacity;/*** 创建主异步线程池** @return Executor*/@Bean(name = "asyncExecutor")public Executor asyncExecutor() {return createThreadPool("async-pool-", "MainAsyncTask");}/*** 创建邮件发送专用线程池(可选扩展)** @return Executor*/@Bean(name = "emailExecutor")public Executor emailExecutor() {return createThreadPool("email-pool-", "EmailTask");}/*** 创建线程池通用方法** @param namePrefix 线程名称前缀* @param taskType   任务类型描述(用于日志区分)* @return ThreadPoolTaskExecutor*/private Executor createThreadPool(String namePrefix, String taskType) {// 使用 Spring 提供的 ThreadPoolTaskExecutor,相较于原生 ThreadPoolExecutor,// 更加适合与 Spring 的 @Async 注解配合使用,并且支持更丰富的配置选项。ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// 设置核心线程数,线程池初始化时创建的线程数量executor.setCorePoolSize(corePoolSize);// 设置最大线程数,当任务队列满时,线程池最多可扩容到的线程数量executor.setMaxPoolSize(maxPoolSize);// 设置非核心线程空闲存活时间(单位为秒)executor.setKeepAliveSeconds(keepAliveSeconds);// 设置任务队列容量,用于缓存待执行的任务executor.setQueueCapacity(queueCapacity);// 设置线程工厂,用于创建具有指定命名前缀的线程,便于日志追踪和问题定位executor.setThreadFactory(createThreadFactory(namePrefix));// 设置拒绝策略:当线程池和任务队列都已满时,由调用线程(即提交任务的线程)自己执行该任务executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 允许核心线程在空闲时超时并被回收,有助于节省资源(适用于负载波动较大的场景)executor.setAllowCoreThreadTimeOut(true);// 设置线程名称前缀,方便在日志中识别不同线程池中的线程executor.setThreadNamePrefix("[" + taskType + "] ");// 必须显式调用 initialize() 来启动线程池executor.initialize();// 返回配置完成的线程池实例return executor;}/*** 创建线程工厂(统一命名格式)** @param prefix 线程名称前缀* @return ThreadFactory*/private ThreadFactory createThreadFactory(String prefix) {return new ThreadFactoryBuilder().setNamePrefix(prefix).build();}@Overridepublic Executor getAsyncExecutor() {return asyncExecutor();}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return new GlobalAsyncUncaughtExceptionHandler();}/*** 异步任务全局异常处理器,这里可以单独放一个类文件(这里鉴于篇幅写在一起)*/@Slf4jpublic static class GlobalAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {@Overridepublic void handleUncaughtException(Throwable ex, Method method, Object... params) {log.error("[Async Task Error] Method: {}, Params: {}", method.getName(), Arrays.deepToString(params), ex);}}
}

application.yml配置(已有默认值,看个人需求配置)

# 全局线程池相关配置
async:executor:core-pool-size: 10max-pool-size: 50keep-alive-seconds: 60queue-capacity: 200

四、自定义线程池使用

在业务开发中,建议每块业务区分线程池使用,模块互不影响,便于日志收集。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、阻塞队列和拒绝策略

Java 中常用的阻塞队列(BlockingQueue)

队列类型特点适用场景
ArrayBlockingQueue基于数组、有界、FIFO内存敏感、任务量可控的系统
LinkedBlockingQueue基于链表、可有界也可无界、FIFO通用型,吞吐量要求较高
PriorityBlockingQueue支持优先级排序、无界需要按优先级处理的任务(如报警、日志级别)
SynchronousQueue不存储元素,插入必须等待取出高并发、低延迟场景,任务直接由消费者线程执行

🚫 线程池拒绝策略(RejectedExecutionHandler)

策略类名行为说明使用建议
AbortPolicy抛出异常 RejectedExecutionException默认策略,适用于不能丢失任务的场景
CallerRunsPolicy由调用线程自己执行任务减缓提交速度,适合临时过载时
DiscardOldestPolicy丢弃队列中最老的任务,尝试重新提交当前任务可接受部分任务丢失,希望保留最新任务
DiscardPolicy默默丢弃任务,不做任何处理可容忍任务丢失,如非关键日志、监控等任务

在这里插入图片描述
默认使用的是LinkedBlockingQueue队列,建议初始化大小,防止内存溢出。

http://www.dtcms.com/wzjs/170487.html

相关文章:

  • 义乌网站建设微信开发百度网盘客服人工电话
  • 洛阳市网站建设抖音seo排名
  • 基于php旅游网站的毕业设计seo提升排名技巧
  • 上海seo网站建设收录查询站长工具
  • 旅游景点网站策划书微信怎么引流营销呢
  • 中国建设银行网站软件优化绿松石什么意思
  • 东莞外贸企业网站建设关联词有哪些小学
  • 资讯网站开发需求石家庄最新疫情最新消息
  • PHP MySQL 网站开发实例线上购买链接
  • 幼儿园微信网站怎么做长沙百度快照优化排名
  • 网站怎么做虚拟连接昨日凌晨北京突然宣布重大消息
  • 男人直接做的视频网站朋友圈软文范例
  • 企业营销型网站建设费用军事网站大全军事网
  • 网站排名提升软件关键词优化的发展趋势
  • 装修网站开发前的准备工作站长素材官网免费
  • 销售渠道都有哪些seo培训学院官网
  • 来宾网站优化桔子seo工具
  • 一级a做爰片免费的网站有吗昆山网站制作哪家好
  • 新疆生产建设兵团棉麻公司网站安徽百度seo公司
  • 天津网站建设排名肇庆seo排名
  • 网站用哪些系统做的比较好网站关键词快速优化
  • 建立百度网站外贸网站推广方式
  • 什么是营销型网站现在推广用什么平台
  • 网站是用什么技术做的北京网络营销策划公司
  • 自己做游戏app的网站宁波网络推广公司有哪些
  • 四川华海建设集团有限公司网站谷歌推广一年多少钱
  • 广州做网站多少钱广州谷歌seo
  • 网站后台帐号厦门人才网唯一官网
  • 综合门户型网站有哪些seo01网站
  • flash怎么做网站北京网站建设东轩seo