线程池的使用案例一

一、配置线程池

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.mzph.cn/news/26026.shtml

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

相关文章

基于Java+SpringBoot+Vue的篮球竞赛预约平台设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

C# 简单模拟 程序内部 消息订阅发布功能

文章目录 前言模拟消息订阅发布使用注意事项 前言 我想做个简单的消息发布订阅功能&#xff0c;但是发现好像没有现成的工具类。要么就是Mqtt这种消息订阅发布。但是我只想程序内部进行消息订阅发布&#xff0c;进行程序的解耦。那没办法了&#xff0c;只能自己上了 模拟消息…

【JavaSE】String类中常用的字符串方法(超全)

目录 1.求字符串的长度 2.判断字符串是否为空 3.String对象的比较 3.1 判断字符串是否相同 3.2 比较字符串大小 3.3 忽略大小写比较 4.字符串查找 5.转化 5.1 数值和字符串转化 5.1.1 数字转字符串 valueof 5.1.2 valueOf的其他用法 5.1.3 字符串转数字 5.2 大小写转…

【Shell】基础语法(二)

文章目录 一、Shell基本语法文件名代换命令代换算术代换转义字符引号 二、Shell脚本语法条件测试分支结构循环 三、总结 一、Shell基本语法 文件名代换 用于匹配的字符称为通配符&#xff08;Wildcard&#xff09;&#xff0c;如&#xff1a;* ? [ ] 具体如下&#xff1a; *…

3个月拿下华为测试岗,早知道华为这么好进,我就...

先说一下我的情况&#xff0c;某211本科计算机专业&#xff0c;之前在深圳那边做了大约半年多少儿编程老师&#xff0c;之后内部平调回长沙这边&#xff0c;回来之后发现有点难&#xff0c;这边可能是业绩难做&#xff0c;虚假承诺很厉害&#xff0c;要给那些家长虚假承诺去骗人…

暗黑版GPT流窜暗网 降低犯罪门槛

随着AIGC应用的普及&#xff0c;不法分子利用AI技术犯罪的手段越来越高明&#xff0c;欺骗、敲诈、勒索也开始与人工智能沾边。 近期&#xff0c;专为网络犯罪设计的“暗黑版GPT”持续浮出水面&#xff0c;它们不仅没有任何道德界限&#xff0c;更没有使用门槛&#xff0c;没有…

EtherCAT转Profinet网关连接西门子PLC与凯福科技总线步进驱动器通讯

西门子S7-1200/1500系列的PLC&#xff0c;采用Profinet实时以太网通讯协议&#xff0c;需要连接带EtherCAT的通讯功能的伺服驱动器等设备&#xff0c;就必须进行通讯协议转换。捷米特JM-EIP-RTU系列的网关提供了&#xff0c;快速可行的解决方案 捷米特JM-ECTM-PN在PROFINET一侧…

tomcat

1. 简述静态网页和动态网页的区别。 静态网页是指在服务器存储的网页内容保持不变&#xff0c;不会根据用户的请求或其他条件而改变。它的内容是固定的&#xff0c;无法根据用户的不同需求进行个性化或实时更新。静态网页一般由HTML、CSS和JavaScript等静态资源组成&#xff0…

linux文件描述符fd

文件描述符 fd是一个>0 的整数 每打开一个文件&#xff0c;就创建一个文件描述符&#xff0c;通过文件描述符来操作文件 预定义的文件描述符: 0:标准输入&#xff0c;对应于已打开的标准输入设备(键盘) 1:标准输出&#xff0c;对应于已打开的标准输出设备(控制台) 2.标准错误…

java异常机制分析

java异常机制分析 本文实例分析了java的异常机制&#xff0c;分享给大家供大家参考。相信有助于大家提高大家Java程序异常处理能力。具体分析如下&#xff1a; 众所周知&#xff0c;java中的异常(Exception)机制很重要&#xff0c;程序难免会出错&#xff0c;异常机制可以捕获…

智慧水利整体解决方案[43页PPT]

导读&#xff1a;原文《智慧水利整体解决方案[43页PPT]》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 完整版领取方式 完整版领取方式&#xff1a; 如需获取完整的…

LNMP及论坛搭建(第一个访问,单节点)

LNMP&#xff1a;目前成熟的一个企业网站的应用模式之一&#xff0c;指的是一套协同工作的系统和相关软件 能够提供静态页面服务&#xff0c;也可以提供动态web服务&#xff0c;LNMP是缩写 L&#xff1a;指的是Linux操作系统。 N&#xff1a;指的是nginx&#xff0c;nginx提…

Doris(四)-Rollup 使用

1&#xff0c;基本语法 1.1 新增 alter table user_landing_record_newadd rollup succ_login_count_index(user_id,day_succ_login_count); 1.2删除 alter table user_landing_record_newdrop rollup succ_login_count_index; 1.3其他操作&#xff0c;参考官网 传送门 …

CSP-J2019初赛试题客观题详解

1、中国的国家顶级域名是() A. .cn B. .ch C. .chn D. .China 【答案】A 【解析】 常见的顶级域名还有&#xff1a;.com表示商业机构&#xff1b;.org表示非盈利性组织&#xff1b;.net表示网络服务机构&#xff1b; .gov表示政府部门&#xff1b;.edu表示…

密码攻击与ADSelfService Plus的保护

密码攻击是当前网络安全面临的严峻挑战之一。黑客通过不断演进的技术手段&#xff0c;试图入侵用户账户&#xff0c;窃取敏感信息&#xff0c;从而对个人和组织造成严重损害。为了应对密码攻击的威胁&#xff0c;ManageEngine推出了ADSelfService Plus&#xff0c;这是一款功能…

流程图如何制作?5步快速画出好看的流程图!

流程图是一种图形化工具&#xff0c;描述某个过程或者操作的步骤&#xff0c;以及某种业务系统的具体流程。流程图通常由各种图形符号、形状、箭头组成&#xff0c;可以清晰的表示出流程或系统中各种步骤、每个环节之间的关系、条件判断、数据的流动和处理过程等。 在线流程图软…

【LeetCode每日一题】——85.最大矩形

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 矩阵 二【题目难度】 困难 三【题目编号】 85.最大矩形 四【题目描述】 给定一个仅包含 0 …

【基础类】—三栏页面布局的方案和优缺点

一、假设高度已知&#xff0c;中间宽度自适应&#xff0c;三栏&#xff08;列&#xff09;布局的方案有哪些&#xff1f; float浮动、absolute绝对定位、flex弹性盒子、table表格布局、grid网格布局 浮动 float <style>* {margin: 0;padding: 0;}.container {width: 1…

内网穿透-————SSH远程连接树莓派

前言 文章目录 前言内网穿透实现公网SSH远程连接树莓派1. 在树莓派上安装[cpolar客户端](https://www.cpolar.com/)2. 在树莓派浏览器中输入本地9200端口3. 在公共互联网的电脑的命令行界面输入命令 内网穿透实现公网SSH远程连接树莓派 随着科技的进步和信息技术的发展&#x…

shell 入门练习小记

一、hello world #!/bin/bash echo "Hello World !"#! 为约定的标记&#xff0c;告诉系统这个脚本需要什么解释器执行&#xff0c;后接绝对路径 /bin/bash 表示期望 bash去解析并运行shell echo用于向窗口输出文本 chmod x ./test.sh #给脚本赋执行权限 ./test.sh …