6/11打卡 异步、线程池
1、异步
即把复杂的任务交付给其他的线程。因为当一个任务执行时间过长时,用户会长时间等待响应,导致体验下降,此时可以使用异步,让用户可以浏览其他内容或者说再提交其他图片任务。
2、线程
线程管理十分麻烦,新增线程、减少线程、闲置线程、接受任务、拒绝任务、保证不抢到同一任务。
当任务来临时,线程们如何不抢占同一个任务?(1、用的线程安全队列,任务只能被一个线程取出 2、每个线程执行任务时加锁,防止并发修改)
因此,我们之间直接线程池,yupi推荐使用JUC并发包中的线程池,一键配置线程
先写配置
▼java复制代码// config/ThreadPoolExecutorConfig package com.zxw.bi_intelligence.config; import org.jetbrains.annotations.NotNull; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.*; @Configuration public class ThreadPoolExecutorConfig { // 创建一个JUC线程池 @Bean public ThreadPoolExecutor threadPoolExecutor(){ // 初始化所有参数 // 核心线程数 int corePoolSize = 2; // 最大线程数 int maximumPoolSize = 4; // 线程空闲时间 long keepAliveTime =60L; // 时间单位 TimeUnit unit=TimeUnit.SECONDS; // 阻塞队列 // LinkedBlockingQueue 链表(Node 节点) 若不配置参数、则默认为Integer.MAX_VALUE // ArrayBlockingQueue 数组 必须指定队列大小 BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(4); // 线程工厂 ThreadFactory threadFactory = new ThreadFactory() { private int count=1; @Override // 每当线程池需要创建新线程时,就会调用newThread方法 // @NotNull Runnable r 表示方法参数 r 应该永远不为null, // 如果这个方法被调用的时候传递了一个null参数,就会报错 public Thread newThread(@NotNull Runnable r) { // 创建一个新的线程 Thread thread = new Thread(r); // 给新线程设置一个名称,名称中包含线程数的当前值 thread.setName("线程" + count + "号"); // 线程数递增 count++; // 返回新创建的线程 return thread; } }; /** * 拒绝策略:当线程池和队列都饱和时的处理方式 * CallerRunsPolicy:由调用线程(提交任务的线程)直接执行该任务 * 其他可选策略: * - AbortPolicy(默认):直接抛出RejectedExecutionException * - DiscardPolicy:静默丢弃无法处理的任务 * - DiscardOldestPolicy:丢弃队列中最旧的任务,然后重试执行 */ RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy(); return new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue ,threadFactory,rejectedExecutionHandler); } }
具体使用(测试)
▼java复制代码// 加载线程池配置 @Resource private ThreadPoolExecutor threadPoolExecutor; @GetMapping("/testAdd") public BaseResponse<String> addThreadTask(String name){ CompletableFuture.runAsync(()->{ // 打印一条日志信息,包括任务名称和执行线程的名称 log.info("任务执行中:" + name + ",执行人:" + Thread.currentThread().getName()); try { // 让线程休眠10分钟,模拟长时间运行的任务 Thread.sleep(600000); } catch (InterruptedException e) { e.printStackTrace(); } // 异步任务在threadPoolExecutor中执行 },threadPoolExecutor); return ResultUtils.success("successd"); } @GetMapping("/testQuery") public BaseResponse<String> queryThreadTask(){ Map<String,Object> map = new HashMap<>(); // 获取线程池的队列长度 int size = threadPoolExecutor.getQueue().size(); // 将队列长度放入map中 map.put("队列长度", size); // 获取线程池已接收的任务总数 long taskCount = threadPoolExecutor.getTaskCount(); // 将任务总数放入map中 map.put("任务总数", taskCount); // 获取线程池已完成的任务数 long completedTaskCount = threadPoolExecutor.getCompletedTaskCount(); // 将已完成的任务数放入map中 map.put("已完成任务数", completedTaskCount); // 获取线程池中正在执行任务的线程数 int activeCount = threadPoolExecutor.getActiveCount(); // 将正在工作的线程数放入map中 map.put("正在工作的线程数", activeCount); // 将map转换为JSON字符串并返回 return ResultUtils.success(JSONUtil.toJsonStr(map)); }
关键参数:corePoolSize、maximumPoolSize、队列长度
我们可以将任务分类为I/O密集型(吃带宽/内存/硬盘的读写资源)和计算密集型(吃 CPU)
I/O密集型:corePoolSize可以设置为2n
计算密集型:corePoolSize可以设置为n+1(设置过大则操作系统频繁通过时间片轮转算法进行线程调度,频繁的切换上下文,严重影响性能,可能切换的消耗比执行时间都长)
设置的数值还需要根据服务器的性能,执行时的情况动态进行调整
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
内容推荐
Day 24✅ 今天做了:1、扇贝英语单词打卡2、英语听说读写、听力练习3、微信阅读15分钟4、编程导航学习⏰ 明天计划:待定📚 今日感悟:Keep going!
1
Day 103✅ 今天做了:复习了多用户通信系统⏰ 明天计划:学习Java反射
0
Day 68时间19:00~ 22:00(3h)✅ 今天做了:Component注解、Mybatis配置、使用⏰ 明天计划:Lombok、Mapper映射、动态SQL📚 今日感悟:自动配置类DataSourceAutoConfiguration ,会读取properties文件,通过注解:@EnableConfigurationProperties(DataSourceProperties.cl
1
Day 19✅ 今天做了:MCP⏰ 明天计划:AI智能体构建📚 今日感悟:今天MCP问题有点多有点杂,明天找时间再捋一下。继续加油
0
Day 25✅ 今天做了:1、扇贝英语单词打卡2、英语听说读写、听力练习3、微信阅读15分钟4、编程导航学习⏰ 明天计划:待定📚 今日感悟:Keep going!
1
