//新建线程池
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、以及数据库批量插入 添加配置优化插入与计算的更多相关文章

  1. jsp采用数据库连接池的方法获取数据库时间戳context.xml配置,jsp页面把时间格式化成自己需要的格式

    <?xml version="1.0" encoding="UTF-8"?> <!-- 数据库连接池配置文件 --> <Conte ...

  2. 基于SmartThreadPool线程池技术实现多任务批量处理

    一.多线程技术应用场景介绍 本期同样带给大家分享的是阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何采用基于开源组件SmartThreadPool线程池技术实现多任务批量处理.在工作中您是否 ...

  3. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  4. 线程池 队列 synchronized

    线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...

  5. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  6. 从线程池到synchronized关键字详解

    线程池 BlockingQueue synchronized volatile 前段时间看了一篇关于"一名3年工作经验的程序员应该具备的技能"文章,倍受打击.很多熟悉而又陌生的知识 ...

  7. JAVA线程池的实际运用

    线程池的创建 我们可以通过ThreadPoolExecutor来创建一个线程池 /** * @param corePoolSize 线程池基本大小,核心线程池大小,活动线程小于corePoolSize ...

  8. 论如何优雅的自定义ThreadPoolExecutor线程池

    更好的markDown阅读体验可直接访问我的CSDN博客:https://blog.csdn.net/u012881584/article/details/85221635 前言 线程池想必大家也都用 ...

  9. Java线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  10. Java并发(四)线程池使用

    上一篇博文介绍了线程池的实现原理,现在介绍如何使用线程池. 目录 一.创建线程池 二.向线程池提交任务 三.关闭线程池 四.合理配置线程池 五.线程池的监控 线程池创建规范 一.创建线程池 我们可以通 ...

随机推荐

  1. linux扩展与缩减lv大小

    在线扩展lv 给vg添加新的pv并扩展lv大小 将新加磁盘生成pv pvcreate /dev/sdd 将pv加入vg vgextend vg_name /dev/sdd 先扩展lv物理边界,大小增加 ...

  2. C# const, readonly, static readonly

    转: Const 定义的是静态常在对象初始化的时候赋值.以后不能改变它的值.属于编译时常量.不能用new初始化. Readonly 是只读变量.属于运行时变量.可以在类constructor里改变它的 ...

  3. py07-文件处理

    """什么是文件? 操作系统提供给用户操作复杂硬件(硬盘)的简易的接口 为什么操作文件 人或者应用程序需要永久的保存数据 如何用 f = open() f.read() ...

  4. MySQL升级5.7.29

    采用卸载后升级的方式 参考:https://blog.csdn.net/liu_dong_mei_mei/article/details/104010567 1.卸载原有的MySQL: 之前是wind ...

  5. java的排序问题

    普通排序 对于基础数据类型的排序,基本只是调用一下方法 如java的 1 Arrays.sort(nums); 那么如何自定义排序规则呢? 自定义排序规则: 假设现在有这么个问题,有n个学生, 每个学 ...

  6. 集群分发xsync xcall kafka启动脚本命令,命令方式安装epel源

    安装epel库源 yum install epel-release -y --nogpgcheck yum install glances 安装开始 建立hosts 白名单 127.0.0.1 loc ...

  7. selenium爬取PDF预览文件

    python selenium 爬取某网站的pdf预览文件,下载图片转换pdf 参考链接:https://blog.csdn.net/weixin_44740756/article/details/1 ...

  8. flink udaf函数

    1.Flink-sql自定义UDAF函数 - 简书 (jianshu.com) 2.Flink SQL 自定义UDAF_k_wzzc的博客-CSDN博客_flink udaf 3.Flink 实践教程 ...

  9. 把VScode插件提示abc的提示给移到最后

    把VScode插件提示abc的提示给移到最后 解决方法 打开设置,在搜索中输入editor.snippetSuggestions,然后将选项改为top,就可以解决了 top:就是将你插件提示放到最上面 ...

  10. redis过期事件监听

    1 修改 redis.conf配置文件: K Keyspace events, published with keyspace@ prefix事件 E Keyevent events, publish ...