线程池的使用案例一

一、配置线程池

1、不推荐的方式

ExecutorService executorService = Executors.newFixedThreadPool();  // 创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待;
ExecutorService executorService = Executors.newCachedThreadPool();  // 创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
ExecutorService executorService = Executors.newSingleThreadExecutor();  // 创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
ExecutorService executorService = Executors.newScheduledThreadPool();  // 创建⼀个可以执⾏延迟任务的线程池;
ExecutorService executorService = Executors.newSingleThreadScheduledExecutor();  // 创建⼀个单线程的可以执⾏延迟任务的线程池;
ExecutorService executorService = Executors.newWorkStealingPool();  // 创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK1.8 添加】。

2、原始方式

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class ThreadPoolUtil {// 核心线程数private static int corePoolSize =10;// 最大线程数private static int maxmumPoolSize =30;// 空闲存活时间private static long keepTime = 30;// 时间单位private static TimeUnit unit = TimeUnit.SECONDS;// 任务队列private static ArrayBlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(1000);// 创建线程工厂private static ThreadFactory threadFactory1 =  Executors.defaultThreadFactory();private static ThreadPoolExecutor.AbortPolicy policy = new ThreadPoolExecutor.AbortPolicy();public static void main(String[] args) throws Exception{ExecutorService executorService1 = Executors.newFixedThreadPool(10);ExecutorService executorService = new ThreadPoolExecutor(corePoolSize,maxmumPoolSize,keepTime,unit,blockingQueue,threadFactory1,policy);executorService.execute(new Runnable(){public void run(){System.out.println("new Runnable!");};});/*//线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行。executorService.shutdownNow();*//*//线程池拒接收新提交的任务,同时等待线程池里的任务执行完毕后关闭线程池。executorService.shutdown();*/// 这个方法会使线程等待timeout时长,当超过timeout时间后,会监测ExecutorService是否已经关闭,若关闭则返回true,// 否则返回false,一般情况下会和shutdown方法组合使用。boolean boole = executorService.awaitTermination(3,TimeUnit.SECONDS);}}

3、Spring的方式

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;@Configuration
@EnableAsync  // 同一个类的中调用无效
public class ThreadPoolConfig {// 获取服务器的cpu个数private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // 获取cpu个数// 核心线程数private static final int COUR_SIZE = CPU_COUNT * 2;// 最大线程数private static final int MAX_COUR_SIZE = CPU_COUNT * 4;// 队列容量private static final int QUEUE_SIZE = CPU_COUNT * 4 * 4;// 空闲存活时间private static long keepTime = 30;// 时间单位private static TimeUnit unit = TimeUnit.SECONDS;// 任务队列// private static ArrayBlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(10*10000);@Bean(name = "asyncDownLoadExcelExecutor")public ThreadPoolTaskExecutor threadPoolTaskExecutor() {// ThreadPoolTaskSchedulerThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();// 设置核心线程数threadPoolTaskExecutor.setCorePoolSize(COUR_SIZE);// 配置最大线程数threadPoolTaskExecutor.setMaxPoolSize(MAX_COUR_SIZE);// 配置队列容量(这里设置成最大线程数的四倍)threadPoolTaskExecutor.setQueueCapacity(QUEUE_SIZE);// 默认是 60s,这里设置 30sthreadPoolTaskExecutor.setKeepAliveSeconds(30);// 给线程池设置名称threadPoolTaskExecutor.setThreadNamePrefix("async-download-excel");threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 设置任务的拒绝策略return threadPoolTaskExecutor;}@Bean(name = "asyncUploadExcelExecutor")public ThreadPoolTaskExecutor asyncUploadExcelExecutor() {ThreadPoolTaskExecutor threadPoolTaskExecutor =  new ThreadPoolTaskExecutor();// 设置核心线程数threadPoolTaskExecutor.setCorePoolSize(5);// 设置最大线程数threadPoolTaskExecutor.setMaxPoolSize(10);// 设置阻塞队列大小threadPoolTaskExecutor.setQueueCapacity(999);// 默认是 60s,这里设置30sthreadPoolTaskExecutor.setKeepAliveSeconds(30);// 设置线程池中线程名前缀threadPoolTaskExecutor.setThreadNamePrefix("async-upload-excel");//当达到 MaxPoolSize 不再调用新线程,用调用者所在线程之星异步任务。threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return threadPoolTaskExecutor;}}

二、百万数据的导出(生成多个文件,统一压缩)

2.1、引入依赖

 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.0.1</version></dependency>

2.2、实体类

public class PersonEntity {private Long id;private String name;private Integer age;private String address;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}

2.3、Controller

    /*** 导出方法* 此处应注意 线程池拒绝策略 抛出的异常,若任务过大,则走降级方法。*/public void exportMillionData(HttpServletRequest request, HttpServletResponse response) throws IOException {// 表格表头String[] TITLE = new String[]{ "姓名", "年龄", "地址"};// 获取数据进行分割int count = 100*10000; // personService.count();int pageSize = 50000;// 获取批次数int tableNum = count % pageSize == 0 ? (count / pageSize) : (count / pageSize) + 1;// 将数据多线程方式导出到excelCountDownLatch latch = new CountDownLatch(tableNum);for (int i = 0; i < tableNum; i++) {exportDataToExcel(latch, TITLE, pageSize, i);}try {// 阻塞 —— 等待全部执行完latch.await();// 压缩响应// 处理中文名不显示的问题String fileName = URLEncoder.encode("人员信息.zip", "UTF-8");response.setContentType("application/octet-stream;charset=UTF-8");response.setContentType("application/x-zip-compressed;charset=UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName);response.addHeader("Pargam", "no-cache");response.addHeader("Cache-Control", "no-cache");response.addHeader("Access-Contro1-A11ow-0rigin", "*");File zip = ZipUtil.zip(new File("D://file/sys/"));ServletOutputStream output = response.getOutputStream();FileInputStream input = new FileInputStream(zip);byte[] buff = new byte[1024 * 10];int len = 0;while ((len = input.read(buff)) > -1) {output.write(buff, 0, len);}output.flush();output.close();if (zip.exists()) {zip.delete();}} catch (InterruptedException e){e.printStackTrace();}finally {FileUtil.deleteDir(new File("D://file/sys/"));}}

2.4、Service

    /*** 导出数据到 Excel* @param latch    锁* @param TITLE    表格头* @param pageSize 每个sheet的记录数* @param first    表格序号*/@Async("asyncDownLoadExcelExecutor")public void exportDataToExcel(CountDownLatch latch, String[] TITLE, int pageSize, int first) throws IOException {//  IPage page = new Page();//  page.setCurrent(i + 1);//  page.setSize(pageSize);List<PersonEntity> records = new ArrayList<>();// personService.page(page).getRecords();int start = first * pageSize;int end = start + pageSize;String fileName = start + "-" + end + "人员信息" + ".xlsx";// 写出到本地的excel文件中SXSSFWorkbook wb = new SXSSFWorkbook();Sheet sheet = wb.createSheet(fileName);Row row = sheet.createRow(0);Cell cell = null;// 写标题for (int j = 0; j < TITLE.length; j++) {cell = row.createCell(j);cell.setCellValue(TITLE[j]);}// 写内容int rowNum = 1;for (PersonEntity entity : records) {row = sheet.createRow(rowNum++);row.createCell(0).setCellValue(entity.getName());row.createCell(1).setCellValue(entity.getAge());row.createCell(2).setCellValue(entity.getAddress());}fileName = new String(fileName.getBytes(), "UTF-8");File file = new File("D://file/sys/" + fileName);if (!file.exists()) {file.getParentFile().mkdirs();}FileOutputStream outputStream = new FileOutputStream(file);wb.write(outputStream);outputStream.flush();outputStream.close();latch.countDown();}

三、多线程插入数据 (类似分布式的TCC)

1、引入依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.9.RELEASE</version>
</dependency>

2、定义线程池

@Bean(name = "asyncInsertDataExecutor")
public ThreadPoolTaskExecutor asyncUploadExcelExecutor() {ThreadPoolTaskExecutor threadPoolTaskExecutor =  new ThreadPoolTaskExecutor();// 设置核心线程数threadPoolTaskExecutor.setCorePoolSize(5);// 设置最大线程数threadPoolTaskExecutor.setMaxPoolSize(10);// 设置阻塞队列大小threadPoolTaskExecutor.setQueueCapacity(999);// 默认是 60s,这里设置30sthreadPoolTaskExecutor.setKeepAliveSeconds(30);// 设置线程池中线程名前缀threadPoolTaskExecutor.setThreadNamePrefix("async-upload-excel");//当达到 MaxPoolSize 不再调用新线程,用调用者所在线程之星异步任务。threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return threadPoolTaskExecutor;
}

3、Controller

@Autowired
private PlatformTransactionManager transactionManager;public String insertData() throws InterruptedException {CountDownLatch latch = new CountDownLatch(10);AtomicReference<Boolean> rollback = new AtomicReference<>(false);// 先在开启多线程外面,定义一个同步集合:List<TransactionStatus> transactionStatuses = Collections.synchronizedList(new ArrayList<>());// 调用线程方法for(int i=0;i<10;i++){exportDataToExcel(latch,rollback,transactionStatuses,new ArrayList<>());}// 阻塞 —— 等待全部执行完latch.await();// 如果出错回滚事务if (rollback.get()) {transactionStatuses.forEach(status -> transactionManager.rollback(status));return " 插入失败 ";} else {transactionStatuses.forEach(status -> transactionManager.commit(status));return " 插入成功 ";}
}

4、Service

@Async("asyncInsertDataExecutor")
public void exportDataToExcel(CountDownLatch latch,AtomicReference<Boolean> rollback,List<TransactionStatus> transactionStatuses,List<Object> list) {try {// 开启事务(可封装成方法)DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);TransactionStatus status = transactionManager.getTransaction(def);transactionStatuses.add(status);// ....  业务代码list.clear();} catch (Exception e) {rollback.set(true);e.printStackTrace();}latch.countDown();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/79322.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一款开源免费、更符合现代用户需求的论坛系统:vanilla

对于个人建站来说&#xff0c;WordPress相信很多读者都知道了。但WordPress很多时候我们还是用来建立自主发布内容的站点为主&#xff0c;适用于个人博客、企业主站等。虽然有的主题可以把WordPress变为论坛&#xff0c;但效果并不是很好。 所以&#xff0c;今天给大家推荐一个…

Mybatis引出的一系列问题-spring多数据源配置

在日常开发中我们都是以单个数据库进行开发&#xff0c;在小型项目中是完全能够满足需求的。但是&#xff0c;当我们牵扯到像淘宝、京东这样的大型项目的时候&#xff0c;单个数据库就难以承受用户的CRUD操作。那么此时&#xff0c;我们就需要使用多个数据源进行读写分离的操作…

考研算法38天:反序输出 【字符串的翻转】

题目 题目收获 很简单的一道题&#xff0c;但是还是有收获的&#xff0c;我发现我连scanf的字符串输入都忘记咋用了。。。。。我一开始写的 #include <iostream> #include <cstring> using namespace std;void deserve(string &str){int n str.size();int…

20230806将ASF格式的视频转换为MP4

20230806将ASF格式的视频转换为MP4 2023/8/6 18:47 缘起&#xff0c;自考中山大学的《计算机网络》&#xff0c;考试《数据库系统原理》的时候找到视频&#xff0c;由于个人的原因&#xff0c;使用字幕更加有学习效率&#xff01; 由于【重型】的PR2023占用资源较多&#xff0c…

通话降噪算法在手机和IOT设备上的应用和挑战

随着电子产品的升级换代&#xff0c;用户对通话质量的要求也越来越高。通话降噪算法对通话质量起到了关键核心的作用。计算资源的提升使得深度学习模型在便携式的低功耗芯片上面跑起来了&#xff0c;器件成本降低让IoT设备开始使用骨导传感器&#xff0c;&#xff0c;那怎么样才…

【秋招】算法岗的八股文之机器学习

目录 机器学习特征工程常见的计算模型总览线性回归模型与逻辑回归模型线性回归模型逻辑回归模型区别 朴素贝叶斯分类器模型 (Naive Bayes)决策树模型随机森林模型支持向量机模型 (Support Vector Machine)K近邻模型神经网络模型卷积神经网络&#xff08;CNN&#xff09;循环神经…

uni-app、H5实现瀑布流效果封装,列可以自定义

文章目录 前言一、效果二、使用代码三、核心代码总结 前言 最近做项目需要实现uni-app、H5实现瀑布流效果封装&#xff0c;网上搜索有很多的例子&#xff0c;但是代码都是不够完整的&#xff0c;下面来封装一个uni-app、H5都能用的代码。在小程序中&#xff0c;一个个item渲染…

网络安全(秋招)如何拿到offer?(含面试题)

以下为网络安全各个方向涉及的面试题&#xff0c;星数越多代表问题出现的几率越大&#xff0c;祝各位都能找到满意的工作。 注&#xff1a;本套面试题&#xff0c;已整理成pdf文档&#xff0c;但内容还在持续更新中&#xff0c;因为无论如何都不可能覆盖所有的面试问题&#xf…

今天开始学习如何正式调查

本节要讲解三个内容 样本容量 调查方式 调查问卷的回收 在正式调查之前需要确定样本容量 就说要准备调查多少人确定好样本容量之后又要考虑设计的调查问卷 是以什么样的方式发出去 问卷的回收又要注意什么问题 要讲的主要内容 先看样本容量 样本容量确定的基本原…

redis+token+分布式锁确保接口的幂等性

目录 1.幂等性是什么&#xff1f; 2.如何实现幂等性呢&#xff1f; 1.新增管理员&#xff0c;出弹窗的同时&#xff0c;请求后台。 2.后端根据雪花算法生成唯一标识key&#xff0c;以雪花数为key存到redis。并返回key给前端。 3.前端保存后端传过来的key。 4.前端输入完成…

Navicat远程连接Linux的MySQL

打开Linux终端&#xff0c;进入root权限&#xff0c;用vim打开MySQL的配置文件 vim /etc/mysql/mysql.conf.d/mysqld.cnf将bind-address的值改为0.0.0.0 进入MySQL mysql -u root -p 将root用户改为允许远程登录 update user set host % where user root; 创建用户 CRE…

【C++奇遇记】函数探幽(上)

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集 数据库专栏 初阶数据结构 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如…

玩转SWAT模型——最全面SWAT模型教程【建模方法、实例应用、高级进阶】

目录 第一部分&#xff1a;SWAT模型实践部分 第二部分&#xff1a;SWAT模型【进阶部分】 更多推荐 【专家】&#xff1a;刘老师【副教授】&#xff0c;北京重点高校资深专家&#xff0c;和美国SWAT软件开发方长期合作&#xff0c;拥有丰富的科研及工程技术经验&#xff0c;长…

node.js安装

下载 https://nodejs.org/en 安装 D:\Program Files\nodejs 配置 D:\Program Files\nodejs 目录下新建 node_cache 和 node_global 在cmd管理员身份运行&#xff1a; npm config set prefix "D:\Program Files\nodejs\node_global" npm config set cache &qu…

Netty 粘包半包

什么是 TCP 粘包半包&#xff1f; 假设客户端分别发送了两个数据包 D1 和 D2 给服务端&#xff0c;由于服务端一次读取到的字节 数是不确定的&#xff0c;故可能存在以下 4 种情况。 &#xff08;1&#xff09;服务端分两次读取到了两个独立的数据包&#xff0c;分别…

手机变电脑2023之虚拟电脑droidvm

手机这么大的内存&#xff0c;装个app来模拟linux&#xff0c;还是没问题的。 app 装好后&#xff0c;手指点几下确定按钮&#xff0c;等几分钟就能把linux桌面环境安装好。 不需要敲指令&#xff0c; 不需要对手机刷机&#xff0c; 不需要特殊权限&#xff0c; 不需要找驱…

怎么快速搭建BI?奥威BI系统做出了表率

搭建BI系统有两大关键&#xff0c;分别是环境搭建和数仓建设。这两点不管是哪一个都相当地费时费力&#xff0c;那要怎么才能快速搭建BI平台&#xff0c;顺利实现全企业数字化运营决策&#xff1f;奥威BI系统方案&#xff0c;你值得拥有&#xff01; 奥威BI系统方案&#xff0…

剑指Offer06. 从尾到头打印链表

# 06. 从尾到头打印链表 目录 # 06. 从尾到头打印链表题目代码&#xff08;双指针法&#xff09;代码逻辑 递归法代码设计流程 题目 官方地址 代码&#xff08;双指针法&#xff09; /*** Definition for singly-linked list.* public class ListNode {* int val;* L…

【计算机视觉 | Kaggle】飞机凝结轨迹识别 Baseline 分享和解读(含源代码)

文章目录 一、导读二、比赛背景三、比赛任务四、比赛数据五、评价指标六、Baseline6.1 Training part6.2 Submission part 一、导读 比赛名称&#xff1a;Google Research - Identify Contrails to Reduce Global Warming https://www.kaggle.com/competitions/google-researc…

【计算机网络】UDP协议

文章目录 1. UDP简介2. TCP和UDP的区别3. UDP的报文格式4. UDP的应用场景 1. UDP简介 UDP和TCP都是传输层协议&#xff0c;用于在计算机网络中发送和接收数据。数据可以是视频,可以是图片,可以是文字等.与TCP相比&#xff0c;UDP不提供数据传输的可靠性和流控制功能&#xff0…