Java使用多线程异步执行批量更新操作
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils; import java.util.List; /**
* 拆分结合工具类
*
* @author shiwen
* @date 2020/12/27
*/
public class SplitListUtils { /**
* 拆分集合
*
* @param <T> 泛型对象
* @param resList 需要拆分的集合
* @param subListLength 每个子集合的元素个数
* @return 返回拆分后的各个集合组成的列表
* 代码里面用到了guava和common的结合工具类
**/
public static <T> List<List<T>> split(List<T> resList, int subListLength) {
if (CollectionUtils.isEmpty(resList) || subListLength <= 0) {
return Lists.newArrayList();
}
List<List<T>> ret = Lists.newArrayList();
int size = resList.size();
if (size <= subListLength) {
// 数据量不足 subListLength 指定的大小
ret.add(resList);
} else {
int pre = size / subListLength;
int last = size % subListLength;
// 前面pre个集合,每个大小都是 subListLength 个元素
for (int i = 0; i < pre; i++) {
List<T> itemList = Lists.newArrayList();
for (int j = 0; j < subListLength; j++) {
itemList.add(resList.get(i * subListLength + j));
}
ret.add(itemList);
}
// last的进行处理
if (last > 0) {
List<T> itemList = Lists.newArrayList();
for (int i = 0; i < last; i++) {
itemList.add(resList.get(pre * subListLength + i));
}
ret.add(itemList);
}
}
return ret;
} // 运行代码
public static void main(String[] args) {
List<String> list = Lists.newArrayList();
int size = 1099;
for (int i = 0; i < size; i++) {
list.add("hello-" + i);
}
// 大集合里面包含多个小集合
List<List<String>> temps = split(list, 100);
int j = 0;
// 对大集合里面的每一个小集合进行操作
for (List<String> obj : temps) {
System.out.println(String.format("row:%s -> size:%s,data:%s", ++j, obj.size(), obj));
}
} }
public void threadMethod() {
List<T> updateList = new ArrayList();
// 初始化线程池, 参数一定要一定要一定要调好!!!!
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(20, 50,
4, TimeUnit.SECONDS, new ArrayBlockingQueue(10), new ThreadPoolExecutor.AbortPolicy());
// 大集合拆分成N个小集合, 这里集合的size可以稍微小一些(这里我用100刚刚好), 以保证多线程异步执行, 过大容易回到单线程
List<T> splitNList = SplitListUtils.split(totalList, 100);
// 记录单个任务的执行次数
CountDownLatch countDownLatch = new CountDownLatch(splitNList.size());
// 对拆分的集合进行批量处理, 先拆分的集合, 再多线程执行
for (List<T> singleList : splitNList) {
// 线程池执行
threadPool.execute(new Thread(new Runnable(){
@Override
public void run() {
for (Entity yangshiwen : singleList) {
// 将每一个对象进行数据封装, 并添加到一个用于存储更新数据的list
// ......
// 任务个数 - 1, 直至为0时唤醒await()
countDownLatch.countDown();
}
}
}));
}
try {
// 让当前线程处于阻塞状态,直到锁存器计数为零
countDownLatch.await();
} catch (InterruptedException e) {
throw new BusinessLogException(ResponseEnum.FAIL);
}
// 通过mybatis的批量插入的方式来进行数据的插入, 这一步还是要做判空
if (GeneralUtil.listNotNull(updateList)) {
batchUpdateEntity(updateList);
LogUtil.info("xxxxxxxxxxxxxxx");
}
}
CountDownLatch概念
CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者说起到线程之间的通信(而不是用作互斥的作用)。
CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。计数器初始值为线程的数量。当每一个线程完成自己任务后,计数器的值就会减一。当计数器的值为0时,表示所有的线程都已经完成一些任务,然后在CountDownLatch上等待的线程就可以恢复执行接下来的任务。
CountDownLatch的用法
CountDownLatch典型用法:1、某一线程在开始运行前等待n个线程执行完毕。将CountDownLatch的计数器初始化为new CountDownLatch(n),每当一个任务线程执行完毕,就将计数器减1 countdownLatch.countDown(),当计数器的值变为0时,在CountDownLatch上await()的线程就会被唤醒。一个典型应用场景就是启动一个服务时,主线程需要等待多个组件加载完毕,之后再继续执行。
CountDownLatch典型用法:2、实现多个线程开始执行任务的最大并行性。注意是并行性,不是并发,强调的是多个线程在某一时刻同时开始执行。类似于赛跑,将多个线程放到起点,等待发令枪响,然后同时开跑。做法是初始化一个共享的CountDownLatch(1),将其计算器初始化为1,多个线程在开始执行任务前首先countdownlatch.await(),当主线程调用countDown()时,计数器变为0,多个线程同时被唤醒。
Java使用多线程异步执行批量更新操作的更多相关文章
- 吴裕雄--天生自然JAVA数据库编程:执行数据库更新操作
import java.sql.Connection ; import java.sql.DriverManager ; import java.sql.Statement ; public clas ...
- mybatis执行批量更新update
Mybatis的批量插入这里有http://ljhzzyx.blog.163.com/blog/static/38380312201353536375/.目前想批量更新,如果update的值是相同的话 ...
- mysql批量update更新,mybatis中批量更新操作
在日常开发中,有时候会遇到批量更新操作,这时候最普通的写法就是循环遍历,然后一条一条地进行update操作.但是不管是在服务端进行遍历,还是在sql代码中进行遍历,都很耗费资源,而且性能比较差,容易造 ...
- JDBC操作,执行数据库更新操作
目标: 使用Connection对象取得Statement实例 使用Statement进行数据增删改. Statement接口 要对数据库操作,要使用Statement完成.此接口可以使用Connec ...
- 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML
https://support.microsoft.com/zh-cn/kb/315968 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML Email Prin ...
- mybatis 的批量更新操作sql
转: mybatis 的批量更新操作sql 2018年07月23日 10:38:19 海力布 阅读数:1689 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...
- mongodb批量更新操作文档的数组键
persons文档的数据如下: > db.persons.find(){ "_id" : 2, "name" : 2 }{ "_id" ...
- Spring源码分析——JdbcTemplate执行批量insert操作
最近用到一个方法: @Override public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) thr ...
- Mybatis之批量更新操作
更新单条记录 UPDATE course SET name = 'course1' WHERE id = 'id1'; 更新多条记录的同一个字段为同一个值 UPDATE course SET name ...
随机推荐
- 3D 世界的钥匙「GitHub 热点速览 v.22.08」
有没有想过把身边的物件儿转成 3D 动画,在网页上实现一把?本期特推的项目 Three.js 就是帮你创建 3D 页面的知名开源项目,好玩的 3D 世界在向你招手.除了打开浏览器 3D 世界的钥匙外, ...
- SpringBoot外部配置属性注入
一.命令行参数配置 Spring Boot可以是基于jar包运行的,打成jar包的程序可以直接通过下面命令运行: java -jar xx.jar 那么就可以通过命令行改变相关配置参数.例如默认tom ...
- SpringBoot实现QQ邮件发送
建项目 创建一个SpringBoot项目 改pom,导入相关依赖 org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE & ...
- centos7对外开放端口号
前提:防火墙处于打开状态 1:查看防护墙启动状态:systemctl status firewalld 2:开启:systemctl start firewalld 3:关闭:systemctl s ...
- Linux之history使用技巧
背景: 正常情况下,Linux系统中输入 history 只显示序号和历史命令如下图,但是当我们想要根据历史命令来排查一些故障问题时,无法精确获取该命令执行的详细信息,包括执行时间.执行的用户.是哪 ...
- 【整理】Linux:set -eux
参数 参考原文:https://blog.csdn.net/textdemo123/article/details/100694371 我们经常见到很多设立了脚本 打头会写如下 set -e 或者:s ...
- BI工具数据可视化效果哪家强?我选这款!
BI工具是商业智能(Business Intelligence)软件的英文缩写.目前,商业智能通常被理解为将企业中现有的数据转化为知识,帮助企业做出明智的业务经营决策的工具. 企业经常会为如何选择BI ...
- AndroidMainifest.xml文件属性
1 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 2 package=" ...
- consul-常用命令
1.consul 是B/C架构.服务端和客户端包是一样的.差别在于启动时候的参数. --客户端 ./consul agent -join=172.29.2.65:8301 -bind=172.29.3 ...
- JSP使用转发后引入CSS失效的解决方案
项目目录结构: 正常引入样式: 但是当经过JSP处理,使用转发时地址栏不变,再用此地址引用则会出现引用失败的情况 正确使用方法: ${pageContext.request.contextPath} ...