springboot多线程处理list并返回list结果
业务:
订单(id,用户id)---用户(id,用户名),要求返回订单且带用户名,视图(订单id,用户id,用户名)
目录结构:
代码:
在Application中通过@EnableAsync开启springboot多线程支持
bean:
package com.example.demo.thread.bean; import lombok.Data; import java.time.LocalDateTime; /** * 订单 */ @Data public class Order { private Long id; private Long userId; private LocalDateTime createTime; }
package com.example.demo.thread.bean; import lombok.Data; /** * 返回结果:订单试图 */ @Data public class OrderVO extends Order{ private String userName; }
package com.example.demo.thread.bean; import lombok.Data; /** * 用户 */ @Data public class User { private Long id; private String userName; }
config配置:
package com.example.demo.thread.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor; @Configuration public class ThreadPoolConfig { //获取cpu线程数+1 private static final int threadNum = Runtime.getRuntime().availableProcessors() + 1; // 核心线程池大小 public static int corePoolSize = threadNum; //最大线程数 private int maxPoolSize = 2 * threadNum; //线程池维护线程所允许的空闲时间 1分钟 private int keepAliveSeconds = 60; //队列最大长度 private int queueCapacity = 1024; //线程池名前缀 private static final String threadNamePrefixName = "Async-Test-Service-"; /** * 自定义线程池 * @return */ @Bean(name = "threadPoolTaskExecutor") public ThreadPoolTaskExecutor createThreadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //最大线程数 executor.setMaxPoolSize(maxPoolSize); //核心线程数 executor.setCorePoolSize(threadNum); //线程活跃时间(秒) executor.setKeepAliveSeconds(keepAliveSeconds); //默认线程名称 executor.setThreadNamePrefix(threadNamePrefixName); //阻塞队列容量 executor.setQueueCapacity(queueCapacity); //设置拒绝策略:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); //初始化 executor.initialize(); return executor; } }
service:
package com.example.demo.thread.service; import com.example.demo.thread.bean.OrderVO; import com.example.demo.thread.bean.User; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import java.util.List; import java.util.concurrent.Future; @Service public class OrderService { @Async(value = "threadPoolTaskExecutor") public Future<List<OrderVO>> getData(List<OrderVO> orderVOS, List<User> users) { System.out.println("多线程名: " + Thread.currentThread().getName()); try { //模拟从数据库里查数据 Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //处理数据 orderVOS.stream().forEach(item -> { users.stream().forEach(user -> { if (item.getUserId().equals(user.getId())) { item.setUserName(user.getUserName()); } }); }); //返回对象 Future<List<OrderVO>> result = new AsyncResult<>(orderVOS); return result; } //单线程 public List<OrderVO> getData1(List<OrderVO> orderVOS, List<User> users) { System.out.println("单线程名: " + Thread.currentThread().getName()); //处理数据 orderVOS.stream().forEach(item -> { try { //模拟从数据库里查数据 Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } users.stream().forEach(user -> { if (item.getUserId().equals(user.getId())) { item.setUserName(user.getUserName()); } }); }); return orderVOS; } }
controller:
package com.example.demo.thread.controller; import com.example.demo.thread.bean.OrderVO; import com.example.demo.thread.bean.User; import com.example.demo.thread.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.PostConstruct; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.concurrent.Future; import java.util.stream.Collectors; @RestController @RequestMapping("/order") public class OrderController { private List<OrderVO> orderVOS = new ArrayList<>(); private List<User> users = new ArrayList<>(); @Autowired private OrderService orderService; /** * 初始化数据 */ @PostConstruct public void createData() { //数据量 long dataCount = 10; // 创建订单数据。模拟已经插入到数据库的订单 for (long i = 0; i < dataCount; i++) { OrderVO orderVO = new OrderVO(); orderVO.setId(i + 1); orderVO.setUserId(i + 1); //防止电脑太快,导致都是同一个时间,所以加一个数 orderVO.setCreateTime(LocalDateTime.now().plusSeconds(i)); orderVOS.add(orderVO); } // 创建用户数据。模拟已经插入到数据库的用户 for (long i = 0; i < dataCount; i++) { User user = new User(); user.setId(i + 1); user.setUserName("用户名" + (i + 1)); users.add(user); } orderVOS = orderVOS.stream() .sorted(Comparator.comparing(OrderVO::getCreateTime).reversed()) .collect(Collectors.toList()); } /** * 单线程 * @return */ @GetMapping("/getSingletonOrderDetails") public List<OrderVO> getOrderDetails1() { long startTime = System.currentTimeMillis(); //这里是不同的执行方式(单线程/线程池) List<OrderVO> result = orderService.getData1(orderVOS, users); long endTime = System.currentTimeMillis(); System.out.println("数据量:"+result.size()+",单线程:执行时间:" + (endTime - startTime) + " ms"); return result; } /** * 多线程 * @return */ @GetMapping("/getMultOrderDetails") public List<OrderVO> getOrderDetails() { long startTime = System.currentTimeMillis(); //这里是不同的执行方式(单线程/线程池) Future<List<OrderVO>> future = orderService.getData(orderVOS, users); //返回结果 List<OrderVO> orderVOList = new ArrayList<>(); try { orderVOList = future.get(); } catch (Exception e) { e.printStackTrace(); } long endTime = System.currentTimeMillis(); System.out.println("数据量:"+orderVOList.size()+",多线程:执行时间:" + (endTime - startTime) + " ms"); return orderVOList; } }
测试:
单线程:http://192.168.0.30:8081/order/getSingletonOrderDetails
多线程:http://192.168.0.30:8081/order/getMultOrderDetails
结果:
备注:这里调整数据量的大小