多线程分批处理数据(控制服务器cpu,控制数据库cpu)

package ip;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* 功能描述:总思路,根据业务创建一定数量的线程池,线程池独立处理一批处理完成。
* 处理完成后再从数据库查询数据再次处理数据
*
* @Author:
* @Date: 2023/10/10 13:28
**/
@Slf4j
public abstract class ThreadUtil {

/**
* 处理
*/
public void execute(int oneThreadCount) {
ExecutorService cachedThreadPool = null;
try {
cachedThreadPool = Executors.newFixedThreadPool(10);

// 是否有数据处理
while (hasData()) {
executeByThread(cachedThreadPool, oneThreadCount);
}
} catch (Exception e) {
log.error("==execute==error={}", e);
} finally {
//关闭线程池
if (null != cachedThreadPool) {
cachedThreadPool.shutdown();
}
}
}
/**
* 核心处理类
*/
private void executeByThread(ExecutorService cachedThreadPoo, int oneThreadCount) throws InterruptedException {
List subList = getSubList();

// 数据处理完毕
if (isEmpty(subList)) {
return;
}

// 分批数据
List<List> partSubList = Lists.partition(subList, oneThreadCount);

final CountDownLatch latch = new CountDownLatch(partSubList.size());

for (List part : partSubList) {

cachedThreadPoo.execute(()-> {
// 业务核心逻辑
try {
handleLogic(part);
} catch (Exception e) {
log.error("==handleData=业务逻辑Exception={}", e);
} finally {
//保证程序计数器不管什么场景正常运行,以免引起主线程堵塞
latch.countDown();
}
});
}
//必须等待for结束后才能继续查询然后分线程去处理,防止内存溢出
latch.await();

//清理数据
subList.clear();
}

/**
* 是否还有数据处理
* @return
*/
public abstract boolean hasData();

/**
* 获取多线程处理的一批数据,由应用方决定
* @return
*/
public abstract List getSubList();

/**
* 对数据进行处理
* @param list
*/
public abstract void handleLogic(List list);

/**
* 分批处理
* @param list
* @return
*/
private static boolean isEmpty(List list) {
return (null == list || list.size() == 0);
}

}
posted @   Snowlanhua  阅读(122)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示