线程池使用、countDownLatch、以及数据库批量插入 添加配置优化插入与计算
//新建线程池
ThreadPoolExecutor cpuThreadPoolExecutor = ThreadUtil.getCpuThreadPoolExecutor();
//使用CountdoLatch
final CountDownLatch countDownLatch = new CountDownLatch((int) (selectIpInfoParam.getIpValue2() - selectIpInfoParam.getIpValue1() + 1));
//循环的时候使用线程池执行
for (long i = selectIpInfoParam.getIpValue1(); i <= selectIpInfoParam.getIpValue2(); i++) {
Ip finalIp = ip;
long finalI = i;
cpuThreadPoolExecutor.execute(() -> {
getIpDetail(finalIp, ipDetails, item00, item01, netType, finalI, map);
countDownLatch.countDown();
});
}
try {
//使用countdoLatch 来停顿主线程,直到数值达到零为止
countDownLatch.await();
if (!CollectionUtils.isEmpty(ipDetails)) {
//批量保存可以设置每次存储更多,默认是1000
ipDetailService.saveBatch(ipDetails, 10000);
}
} catch (Exception e) {
throw new ApiException(500, "服务异常!");
}
&rewriteBatchedStatements=true :设置在数据库连接后面,可以使保存批量更快速
public final class ThreadUtil {
private ThreadUtil() {
}
/**
* 最大线程上并非越大越快,别瞎整,需要实际调试
*/
private static final int MAX_THREAD_COUNT = 15;
/**
* CPU 数量
*/
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
public static <T> ThreadPoolExecutor getIOThreadPoolExecutor() {
return getThreadPoolExecutor(CPU_COUNT << 4, CPU_COUNT << 5, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory());
}
public static <T> ThreadPoolExecutor getCpuThreadPoolExecutor() {
return getThreadPoolExecutor(CPU_COUNT + 1, CPU_COUNT *2, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory());
}
private static <T> ThreadPoolExecutor getThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit timeUnit, BlockingQueue<Runnable> queue, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, queue, threadFactory);
}
public static <T> void execute(ThreadPoolExecutor poolExecutor, Collection<T> collection, Consumer<T> consumer, int threadCount) {
// 空集合
if (CollectionUtils.isEmpty(collection)) {
return;
}
// 处理数量小于等于2 不开启子线程
if (collection.size() <= 2) {
collection.forEach(consumer);
return;
}
// 将request设置为子线程共享
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
BlockingQueue<T> queue = new LinkedBlockingQueue<>(collection);
for (int a = 0; a < threadCount; a++) {
poolExecutor.execute(() -> {
try {
RequestContextHolder.setRequestAttributes(sra);
while (true) {
T t = queue.poll();
if (null == t) {
break;
}
consumer.accept(t);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
RequestContextHolder.resetRequestAttributes();
countDownLatch.countDown();
}
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static <T> void execute(ThreadPoolExecutor poolExecutor, Collection<T> collection, Consumer<T> consumer) {
// 启用线程数量
int threadCount = Math.min((collection.size() >>> 1) + 1, MAX_THREAD_COUNT);
execute(poolExecutor, collection, consumer, threadCount);
}
}
线程池使用、countDownLatch、以及数据库批量插入 添加配置优化插入与计算的更多相关文章
- jsp采用数据库连接池的方法获取数据库时间戳context.xml配置,jsp页面把时间格式化成自己需要的格式
<?xml version="1.0" encoding="UTF-8"?> <!-- 数据库连接池配置文件 --> <Conte ...
- 基于SmartThreadPool线程池技术实现多任务批量处理
一.多线程技术应用场景介绍 本期同样带给大家分享的是阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何采用基于开源组件SmartThreadPool线程池技术实现多任务批量处理.在工作中您是否 ...
- Android(java)学习笔记267:Android线程池形态
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- 线程池 队列 synchronized
线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...
- Java 线程池(ThreadPoolExecutor)原理分析与使用
在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...
- 从线程池到synchronized关键字详解
线程池 BlockingQueue synchronized volatile 前段时间看了一篇关于"一名3年工作经验的程序员应该具备的技能"文章,倍受打击.很多熟悉而又陌生的知识 ...
- JAVA线程池的实际运用
线程池的创建 我们可以通过ThreadPoolExecutor来创建一个线程池 /** * @param corePoolSize 线程池基本大小,核心线程池大小,活动线程小于corePoolSize ...
- 论如何优雅的自定义ThreadPoolExecutor线程池
更好的markDown阅读体验可直接访问我的CSDN博客:https://blog.csdn.net/u012881584/article/details/85221635 前言 线程池想必大家也都用 ...
- Java线程池(ThreadPoolExecutor)原理分析与使用
在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...
- Java并发(四)线程池使用
上一篇博文介绍了线程池的实现原理,现在介绍如何使用线程池. 目录 一.创建线程池 二.向线程池提交任务 三.关闭线程池 四.合理配置线程池 五.线程池的监控 线程池创建规范 一.创建线程池 我们可以通 ...
随机推荐
- 虚拟内存跟物理内存之间的映射mmap\munmap
#include <stdio.h> #include <sys/mman.h> int main(void) { /* * 创建虚拟内存的映射 * void *mmap (v ...
- 博客神器Gridea
博客神器Gridea Gridea 温故而知新 Gridea 最早叫 Hve Notes ,开发者为了更易读和好记,重新命名为 Gridea,支持 Windows 和 Mac 平台,他的基础界面非常的 ...
- 【TensorFlow】Tensorflow-GPU 环境搭建教程(附 Windows 版本对应表及 CUDA GPU 计算能力表)
conda教程(推荐):『Tensorflow GPU Installation Made Easy: Use conda instead of pip [Update-2] | by Harveen ...
- SQL in查询字段为Guid拼接处理办法
场景一:在我们写SQL脚本执行普通的Id 为Int,Long 类型查询为 譬如: select *from Table where id in (1,2,3); 场景二:SQL in 查询,当查询字段 ...
- wake on lan magic packet
局域网模式,必须电脑和手机在同一个 局域网,或者是网段内 外网模式 这个就是,你拿着手机,在任何地方,都可以开机电脑.
- vue store用法
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) 首字母不能大写 export default new Vuex.Store({ ...
- 如何在 Visual Studio 中自定义 Docker 容器 和 使用 Docker Compose 为 Visual Studio 创建多容器应用
https://learn.microsoft.com/zh-cn/visualstudio/containers/container-build?WT.mc_id=visualstudio_cont ...
- 洛谷P4342 [IOI1998]Polygon
题目 https://www.luogu.com.cn/problem/P4342 我会做IOI题辣 思路 算法设计与分析的课堂例题. 首先这是一个环状DP,那么根据老套路,破环成链.发现要求的东西也 ...
- Android studio学习笔记2
Android studio学习笔记2 20201303张奕博 2023.1.14 android studio动态调试apk 1.配置环境 android studio需要安装插件:1,Smalid ...
- java中的批量导入,批量更新数据
批量插入 数据,提高效率 Dao层 int insertBatch(List<HealthImport> list); xml文件 <insert id="insertBa ...