lack——主页前后端开发优化(精华:java多线程实现数据插入)
lack——主页前后端开发优化
前端开发主页
- 最容易的方式:list列表
<template> <van-card v-for="user in props.userList" :desc="user.profile" :title="`${user.username} (${user.planetCode})`" :thumb="user.avatarUrl" > <template #tags> <van-tag plain type="danger" v-for="tag in user.tags" style="margin-right: 8px; margin-top: 8px"> {{ tag }}</van-tag> </template> <template #footer> <van-button size="mini">联系我</van-button> </template> </van-card> </template> <script setup lang="ts"> import {UserType} from "../models/user"; interface UserCardListProps{ userList:UserType[]; } const props = withDefaults(defineProps<UserCardListProps>(),{ // @ts-ignore userList:[] as UserType[], }); </script> <style scoped> </style>
后端接口开发(精华:java多线程实现数据插入)
- 对接主页接口开发
/** * 首页推荐接口 * @param request * @return */ @GetMapping("/recommend") public BaseResponse<List<User>> recommendUsers(HttpServletRequest request) { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); List<User> userList = userService.list(queryWrapper); List<User> list = userList.stream().map(user -> userService.getSafetyUser(user)).collect(Collectors.toList()); return ResultUtils.success(list); }
- 优化对接主页接口开发(分页查询)
/** * 首页推荐接口(分页查询) * @param request * @return */ @GetMapping("/recommend") public BaseResponse<Page<User>> recommendUsers(long pageSize,long pageNum,HttpServletRequest request) { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); Page<User> userList = userService.page(new Page<>(pageNum,pageSize),queryWrapper); return ResultUtils.success(userList); }
- 模拟大量用户状态
- 导入用户数据方式
- 可视化界面导入
- 执行sql语句
- 写程序:使用for循环,可以分批导入(保证可控性)。
- 编写一次性任务批量插入(for循环插入数据问题:建立释放连接,for循环是绝对线性的)
@Component //成为spring bean public class InsertUsers { @Resource private UserMapper userMapper; @Resource private UserService userService; public void doInsertUser(){ StopWatch stopWatch = new StopWatch(); stopWatch.start(); final int INSERT_NUM = 1000; List<User> userList = new ArrayList<>(); for (int i = 0; i < INSERT_NUM; i++) { User user = new User(); user.setUsername("假二哈"); user.setUserAccount("FakeErha"); user.setAvatarUrl("https://tse4-mm.cn.bing.net/th/id/OIP-C.DMY4H6Xibxdrzf-hkElvZgHaDu?w=326&h=176&c=7&r=0&o=5&pid=1.7"); user.setGender(0); user.setUserPassword("12345678"); user.setPhone("13987496799"); user.setEmail("13987496799@qq.com"); user.setUserStatus(0); user.setUserRole(0); user.setPlanetCode("1111111"); user.setTags("[]"); userList.add(user); } userService.saveBatch(userList,100); stopWatch.stop(); System.out.println(stopWatch.getTotalTimeMillis()); } }
- 并发要注意执行的前后顺序无所谓,不要用到非并发类的集合如list
/** * 自定义线程池 * 参数含义:默认多少线程池,最大多少,线程存活时间,线程单位,任务队列 */ private ExecutorService executorService = new ThreadPoolExecutor(60,1000, 10000,TimeUnit.MINUTES,new ArrayBlockingQueue<>(10000)); /** * 并发批量插入数据 */ public void doConcurrencyInsertUser(){ StopWatch stopWatch = new StopWatch(); stopWatch.start(); int batchSize = 5000; //10万条数据分成10组每组1万条 int j = 0; List<CompletableFuture<Void>> futuresList = new ArrayList<>(); for (int i = 0; i <20; i++) { List<User> userList = Collections.synchronizedList(new ArrayList<>()); while (true) { j++; User user = new User(); user.setUsername("假二哈呀"); user.setUserAccount("FakeErha"); user.setAvatarUrl("https://tse4-mm.cn.bing.net/th/id/OIP-C.DMY4H6Xibxdrzf-hkElvZgHaDu?w=326&h=176&c=7&r=0&o=5&pid=1.7"); user.setGender(0); user.setUserPassword("12345678"); user.setPhone("13987496799"); user.setEmail("13987496799@qq.com"); user.setUserStatus(0); user.setUserRole(0); user.setPlanetCode("1111111"); user.setTags("[]"); userList.add(user); if (j % batchSize == 0) { break; } } //新建一个异步的任务,不要返回值,使用此方法里面的操作就是异步的 CompletableFuture<Void> feature = CompletableFuture.runAsync(() -> { System.out.println("ThreadName:" + Thread.currentThread().getName()); userService.saveBatch(userList, batchSize); },executorService); futuresList.add(feature); } CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[]{ })); stopWatch.stop(); System.out.println(stopWatch.getTotalTimeMillis()); }
- 编写一次性任务批量插入(for循环插入数据问题:建立释放连接,for循环是绝对线性的)
- 导入用户数据方式