模拟线程池与异步方法调用查询接口优化
问题:批量查询如何优化?
entity实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | package com.itheima.alipay.prop; import lombok.Data; @Data public class UserInfo { private Long userId; private String username; private int age; public UserInfo(Long userId, String username, int age) { this .userId = userId; this .username = username; this .age = age; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this .userId = userId; } public String getUsername() { return username; } public void setUsername(String username) { this .username = username; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } @Override public String toString() { return "UserInfo{" + "userId=" + userId + ", username='" + username + '\ '' + ", age=" + age + '}' ; } } |
service模拟查询接口,设置睡眠时间模拟查询耗时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | package com.itheima.alipay.prop; import lombok.SneakyThrows; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Service public class TestService { public static List<UserInfo> getUserInfo(List<Long> userIds) throws InterruptedException { long startTime = System.currentTimeMillis(); List<UserInfo> userInfos = new ArrayList<>(); // 模拟调用耗时 Thread.sleep(300); // 预定义的用户信息映射 final List<UserInfo> predefinedUsers = Arrays.asList( new UserInfo(1L, "李白" , 20), new UserInfo(2L, "杜甫" , 22), new UserInfo(3L, "白居易" , 25), new UserInfo(4L, "王维" , 27), new UserInfo(5L, "孟浩然" , 29), new UserInfo(6L, "苏轼" , 31), new UserInfo(7L, "辛弃疾" , 33), new UserInfo(8L, "陆游" , 35), new UserInfo(9L, "韩愈" , 37), new UserInfo(0L, "柳宗元" , 39) ); // 根据传入的userId查找用户信息 for (Long id : userIds) { for (UserInfo userInfo : predefinedUsers) { if (userInfo.getUserId(). equals (id)) { // 模拟调用耗时 Thread.sleep(200); userInfos.add(userInfo); break ; } } } // 计算并打印程序运行时间 long endTime = System.currentTimeMillis(); System. out .println(userInfos); return userInfos; } //public static List<UserInfo> getUserInfo(List<Long> userIds) throws InterruptedException { // long startTime = System.currentTimeMillis(); // // List<UserInfo> userInfos = new ArrayList<>(); // // // 预定义的用户信息映射 // final List<UserInfo> predefinedUsers = Arrays.asList( // new UserInfo(1L, "李白", 20), // new UserInfo(2L, "杜甫", 22), // new UserInfo(3L, "白居易", 25), // new UserInfo(4L, "王维", 27), // new UserInfo(5L, "孟浩然", 29), // new UserInfo(6L, "苏轼", 31), // new UserInfo(7L, "辛弃疾", 33), // new UserInfo(8L, "陆游", 35), // new UserInfo(9L, "韩愈", 37), // new UserInfo(0L, "柳宗元", 39) // ); // // // 使用Map来优化查找 // Map<Long, UserInfo> userMap = predefinedUsers.stream() // .collect(Collectors.toMap(UserInfo::getUserId, userInfo -> userInfo)); // // for (Long id : userIds) { // UserInfo userInfo = userMap.get(id); // if (userInfo != null) { // userInfos.add(userInfo); // } // } // // // 计算并打印程序运行时间 // long endTime = System.currentTimeMillis(); // System.out.println("获取用户信息耗时: " + (endTime - startTime) + "ms"); // System.out.println(userInfos); // // return userInfos; //} @Async( "asyncPoolTaskExecutor" ) @SneakyThrows public List<UserInfo> fetchUserInfoAsync(List<Long> userIds) { long startTime = System.currentTimeMillis(); List<UserInfo> userInfos = getUserInfo(userIds); long endTime = System.currentTimeMillis(); System. out .println( "异步调用耗时:" + (endTime - startTime) + "ms" ); return userInfos; } } |
controller层(便于方便异步方法线程池都写在了controller,实际开发根据需要调整)
package com.itheima.alipay.controller; import com.itheima.alipay.prop.Service; import com.itheima.alipay.prop.TestService; import com.itheima.alipay.prop.UserInfo; import com.itheima.alipay.prop.UserInfoResult; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.PreDestroy; import javax.annotation.Resource; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.*; import java.util.stream.Collectors; @RestController public class db { @Resource private TestService testService; /** * 线程池异步查询,但结果采用了等待全部收集,阻塞相当于线程池并发执行 * 使用 CompletableFuture::join 方法同步等待所有任务完成,并合并结果。 * 整个方法是同步的,尽管任务是异步执行的,但方法本身会阻塞直到所有任务完成。 * @return */ @GetMapping("thread") public String qb() { long startTime = System.currentTimeMillis(); List<Long> userIds = Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 0L); ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池 // 记录启动所有异步任务之前的时间 long startSubmitTime = System.currentTimeMillis(); List<CompletableFuture<List<UserInfo>>> futures = userIds.stream() .map(userId -> CompletableFuture.supplyAsync(() -> { try { return testService.getUserInfo(Collections.singletonList(userId)); // 查询单个userId的信息 } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new CompletionException(e); } }, executor)) .collect(Collectors.toList()); // 打印启动所有异步任务之后的时间 long endSubmitTime = System.currentTimeMillis(); System.out.println("所有异步任务启动完成时间: " + (endSubmitTime - startSubmitTime) + "ms"); // 合并所有CompletableFuture的结果 List<UserInfo> allInfos = futures.stream() .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList()); // 输出结果 System.out.println(allInfos); long endTime = System.currentTimeMillis(); System.out.println("程序运行时间: " + (endTime - startTime) + "ms"); Long time = endTime - startTime; // 关闭线程池 executor.shutdown(); return allInfos + String.valueOf(time); } /** * 线程池异步查询,但结果采用了等待全部收集,阻塞相当于线程池并发执行 * 使用 CompletableFuture.allOf 方法异步等待所有任务完成。 * 使用 thenApply 方法异步构建最终的响应。 * 整个方法是异步的,不会阻塞主线程,适合处理高并发请求。 * @return */ @GetMapping("qb3") public CompletableFuture<ResponseEntity<UserInfoResult>> qb3() { long startTime = System.currentTimeMillis(); List<Long> userIds = Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 0L); ExecutorService executor = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池 // 记录启动异步任务之前的时间 long startSubmitTime = System.currentTimeMillis(); List<CompletableFuture<List<UserInfo>>> futures = userIds.stream() .map(userId -> CompletableFuture.supplyAsync(() -> { try { return testService.getUserInfo(Collections.singletonList(userId)); } catch (Exception e) { e.printStackTrace(); throw new CompletionException(e); } }, executor)) // 将任务提交到线程池 .collect(Collectors.toList()); // 打印启动所有异步任务之后的时间 long endSubmitTime = System.currentTimeMillis(); System.out.println("所有异步任务启动完成时间: " + (endSubmitTime - startSubmitTime) + "ms"); // 合并所有CompletableFuture的结果 CompletableFuture<List<UserInfo>> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) .thenApply(v -> futures.stream() .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList())); // 构建最终的响应 CompletableFuture<ResponseEntity<UserInfoResult>> result = allFutures.thenApply(infos -> { long endTime = System.currentTimeMillis(); long duration = endTime - startTime; System.out.println("程序运行时间: " + duration + "ms"); // 将结果封装为UserInfoResult对象 UserInfoResult userInfoResult = new UserInfoResult(infos, duration); // 返回HTTP响应实体 return ResponseEntity.ok(userInfoResult); }).exceptionally(ex -> { ex.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new UserInfoResult(Collections.emptyList(), -1)); }); executor.shutdown(); return result; } /** * 同步方法执行 * @return */ @GetMapping("now") public String qb1() { try { long startTime = System.currentTimeMillis(); List<Long> userIds = Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 0L); List<UserInfo> infos = testService.getUserInfo(userIds); long endTime = System.currentTimeMillis(); System.out.println("程序运行时间: " + (endTime - startTime) + "ms"); Long time = endTime - startTime; System.out.println(infos); return infos + String.valueOf(time); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Restore interrupted status System.err.println("Thread was interrupted."); return "error"; } } /** * 调用异步任务,接口任务启动即结束,耗时短,适合无需立即查看响应结果的操作 * @return */ @GetMapping("qb4") public CompletableFuture<ResponseEntity<UserInfoResult>> qb4() { long startTime = System.currentTimeMillis(); List<Long> userIds = Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 0L); // 记录启动异步任务之前的时间 long startSubmitTime = System.currentTimeMillis(); System.out.println("Starting to submit async tasks at: " + startSubmitTime); CompletableFuture<List<UserInfo>> futures = CompletableFuture.supplyAsync(() -> { try { List<UserInfo> infos = testService.fetchUserInfoAsync(userIds); System.out.println("Fetched user infos in async method: " + infos); return infos; } catch (Exception e) { e.printStackTrace(); throw new CompletionException(e); } }); // 打印启动异步任务之后的时间 long endSubmitTime = System.currentTimeMillis(); System.out.println("异步任务启动完成时间: " + (endSubmitTime - startSubmitTime) + "ms"); CompletableFuture<ResponseEntity<UserInfoResult>> result = futures.thenApply(infos -> { long endTime = System.currentTimeMillis(); long duration = endTime - startTime; System.out.println("程序运行时间: " + duration + "ms"); // 将结果封装为UserInfoResult对象 UserInfoResult userInfoResult = new UserInfoResult(infos, duration); System.out.println("UserInfoResult created: " + userInfoResult); // 返回HTTP响应实体 return ResponseEntity.ok(userInfoResult); }).exceptionally(ex -> { ex.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new UserInfoResult(Collections.emptyList(), -1)); }); return result; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2023-11-20 实验18:迭代器模式