赞
踩
在数据库中如果需要对大量的数据进行批量修改,并不是一项简单的工作。而利用线程池可以帮助我们解决这些问题
For循环插入5000条记录
- @Test
- void contextLoads6() {
- ArrayList<UserInfo> allUser = new ArrayList<>(5000);
-
- //生成size个UserInfo
- for (int i = 0; i < 5000; i++) {
- UserInfo userInfo = new UserInfo();
- userInfo.setId(String.valueOf(i + 10000));
- allUser.add(userInfo);
- }
-
- long startTime = System.currentTimeMillis();
- for (int i = 0;i<5000;i++){
- mapper.insert(allUser.get(i));
- }
- System.out.println("单线程for循环插入5000耗时:"+(System.currentTimeMillis()-startTime));
- }

- public class InsertTarget implements Callable<Integer> {
-
- private UserInfoMapper mapper;
-
- private List<UserInfo> list;
-
- private CountDownLatch countDownLatch;
-
- public InsertTarget(UserInfoMapper mapper, List<UserInfo> list, CountDownLatch countDownLatch) {
- this.mapper = mapper;
- this.list = list;
- this.countDownLatch = countDownLatch;
- }
-
- @Override
- public Integer call() throws Exception {
- //记录插入成功的条数
- int rows = 0;
- for (UserInfo user :
- list) {
- mapper.insert(user);
- rows++;
- }
-
- //完全插入成功,CountDownLatch-1
- if (rows == list.size()) {
- countDownLatch.countDown();
- }
-
- return rows;
- }
- }

- /**
- * Copyright (C), 2017-2022, 湖南兴盛优选电子商务有限公司.
- *
- * @author 13240
- * @description 针对表【user_info】的数据库操作Service实现
- * @createDate 2022-07-27 10:39:08
- */
- @Slf4j
- @Service
- public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
- implements UserInfoService {
-
- @Autowired
- UserInfoMapper mapper;
-
- @Override
- public Integer insertList(Integer size) {
- //制造数据,list里面有size(5000)个UserInfo
- List<UserInfo> allUser = this.createSizeList(size);
- //线程数
- int threadSize = ?;
-
- ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(threadSize, threadSize, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
- //每个线程处理的数据量
- final Integer dataPartionLength = (allUser.size() + (threadSize) - 1) / (threadSize);
-
- int downLatchSize = 0;
- //将downLatchSize这个值计算出来
- if (size%dataPartionLength==0){
- downLatchSize=size/dataPartionLength;
- }else {
- downLatchSize=size/dataPartionLength+1;
- }
-
- CountDownLatch latch = new CountDownLatch(downLatchSize);
- long startTime = System.currentTimeMillis();
- for (int i = 0; i < downLatchSize; i++) {
- //每个线程均分需要处理的数据
- List<UserInfo> threadDatas = allUser.stream()
- .skip(i * dataPartionLength).limit(dataPartionLength).collect(Collectors.toList());
-
- //调用实现了Callable的InsertTarget类,并将mapper,threadDatas,latch传进去
- InsertTarget insertTarget = new InsertTarget(mapper, threadDatas, latch);
- FutureTask<Integer> futureTask = new FutureTask<>(insertTarget);
-
- //执行任务
- threadPoolExecutor.execute(futureTask);
- }
- try {
- //保证每个线程完成后再完成计时
- latch.await();
- long endTime = System.currentTimeMillis();
- log.info("线程数为{}的线程池插入5000用时:{}",threadSize, endTime - startTime);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return 200;
- }
-
- /**
- * 用来生成数据,返回一个size大小的list
- */
- private List<UserInfo> createSizeList(Integer size) {
- ArrayList<UserInfo> list = new ArrayList<>(100);
-
- //生成size个UserInfo,并放进List
- for (int i = 0; i < size; i++) {
- UserInfo userInfo = new UserInfo();
- userInfo.setId(String.valueOf(i + 1));
- list.add(userInfo);
- }
- return list;
- }
- }

多线程提交修改时,尝试了不同线程数对插入速度的影响,具体可以看下面表格
核心线程数 | 1 | 4 | 5 | 10 | 15 |
---|---|---|---|---|---|
耗时 | 6327 | 3847 | 3036 | 5230 | 4630 |
多线程对数据库进行操作时,并非线程数越多操作越快。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。