多线程例子,通过启动三个线程 等三个线程都跑完后打印结果

一个多线程例子,通过启动三个线程 等三个线程都跑完后打印结果

需求描述:开启一个多线程跑3条门店的数据,每个门店都新起一个线程去跑数据,当所有线程跑完后主线程打印结果,记录报错的门店编码

1.线程池配置类

import com.alibaba.fastjson.JSONObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;/*** 对优惠卷创建设置对线程池默认配置** @author woniu* @date 2024-01-16*/
@Configuration
public class CouponPolicyThreadPoolConfig {/*** CPU核心数(不一定准确,在单核多线程的CPU情况下可能会存在数据的偏差)*/private final static Integer PROCESSINGCOUNT = Runtime.getRuntime().availableProcessors();/*** 该线程池,专门用于优惠政策的数据从持久层加载到进程内存中的工作过程。用于提高加载效率** @return*/@Bean("couponPolicyCreateExecutor")@ConditionalOnMissingBean(name = "couponPolicyCreateExecutor")public ThreadPoolExecutor getCouponPolicyCreateExecutor() {return new ThreadPoolExecutor(PROCESSINGCOUNT, PROCESSINGCOUNT, 1, TimeUnit.HOURS, new LinkedBlockingQueue<>(), new CouponPolicyCreateExecutorThreadFactory());}/*** 获取CouponPolicyCreateTask  bean(多例)* @return*/@Bean@Scope("prototype")public CouponPolicyCreateTask getCouponPolicyCreateTask(String tenantCode, JSONObject salePolicyJson) {return new CouponPolicyCreateTask(tenantCode,salePolicyJson);}/*** 自定义实现优惠卷创建的执行线程工厂*/private class CouponPolicyCreateExecutorThreadFactory implements ThreadFactory {private final AtomicInteger count = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "coupon-create-task-" + count.getAndIncrement());}}}

2.任务类

import com.alibaba.fastjson.JSONObject;
import com.woniu.crm.user.User;
import com.woniu.woniuuser.mapper.UserMapper;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.concurrent.Callable;/*** 优惠卷创建任务类** @author woniu* @date 2024-01-16*/
public class CouponPolicyCreateTask implements Callable<Integer> {/*** 日志*/private static final Logger LOGGER = LoggerFactory.getLogger(CouponPolicyCreateTask.class);@Resourceprivate UserMapper userMapper;/*** 租户编码*/private String tenantCode;/*** 促销政策json*/private JSONObject salePolicyJson;public CouponPolicyCreateTask(String tenantCode, JSONObject salePolicyJson) {this.tenantCode = tenantCode;this.salePolicyJson=salePolicyJson;Validate.notNull(salePolicyJson, "CouponPolicyCreateTask: tenantCode blank !!");Validate.notBlank(tenantCode, "CouponPolicyCreateTask: salePolicyJson null !!");}@Override@Transactionalpublic Integer call() throws Exception {try {LOGGER.info("租户编码"+tenantCode);User user=new User();user.setUsername(tenantCode);userMapper.insert(user);salePolicyJson.put("2","3");if ("1".equals(tenantCode)) {Thread.sleep(1000);throw new RuntimeException("1出现报错");}else{Thread.sleep(2000);}} catch (RuntimeException e) {throw new RuntimeException("出现报错编码为:" + tenantCode);}return 1;}}

3.主线程调用类

/*** 测试多线程* @param* @return*/
@Override
@Transactional(rollbackFor = Exception.class)
public void multiThread(){/*** 需求描述开启一个多线程跑3条门店的数据,每个门店都新起一个线程去跑数据,当所有线程跑完后主线程打印结果,记录报错的门店编码*///1.新建三个门店编码List<String> tenantCodes=new ArrayList<>();for(int i=0;i<3;i++){tenantCodes.add(String.valueOf(i));}log.info("所有任务开始");Set<Future<Integer>> loadingSet = Sets.newLinkedHashSet();String json="{\"salePolicyCode\":\"123\"}";JSONObject jsonObject = JSON.parseObject(json);for(String tenant:tenantCodes){String s = jsonObject.toJSONString();//注意这里必须转成字符串然后去转换 或者将对象重新拷贝,不然所有对象中用的都是同一个jsonObjectJSONObject newJsonObject = JSON.parseObject(s);//通过getBean方式获取taskCouponPolicyCreateTask task = this.applicationContext.getBean(CouponPolicyCreateTask.class, tenant, newJsonObject);//submit方式提交任务Future<Integer> submit = couponPolicyCreateExecutor.submit(task);loadingSet.add(submit);}List<String> failTenantCodes = new ArrayList<>();for(Future<Integer> result:loadingSet){try {//当执行到这里时,get方法会进行阻塞主线程,当执行result任务的线程执行完成后get方法才会释放,程序继往下执行result.get();}catch (ExecutionException | InterruptedException e) {log.error("主线程报错");//通过报错信息截取报错的租户编码String message = e.getMessage();int index = message.indexOf("出现报错租户编码为:");String substring = message.substring(index + 10);failTenantCodes.add(substring);continue;}}log.info("所有任务结束");log.info("出现报错租户编码集合"+JSON.toJSONString(failTenantCodes));}

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

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

相关文章

山西电力市场日前价格预测【2024-02-04】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-04&#xff09;山西电力市场全天平均日前电价为367.56元/MWh。其中&#xff0c;最高日前电价为441.08元/MWh&#xff0c;预计出现在18:30。最低日前电价为324.52元/MWh&#xff0c;预计…

代码混淆技术综述与优化方法

摘要 本文介绍了代码混淆的概念和目的&#xff0c;并提供了Python代码混淆的宏观思路。同时&#xff0c;还介绍了一种在线网站混淆Python代码的方法&#xff0c;并给出了混淆前后的示例代码。 引言 在当今信息时代&#xff0c;软件代码的保护显得尤为重要。代码混淆是一种常…

【数位dp】【动态规划】【KMP】1397. 找到所有好字符串

作者推荐 【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数 本文涉及知识点 动态规划汇总 LeetCode1397. 找到所有好字符串 给你两个长度为 n 的字符串 s1 和 s2 &#xff0c;以及一个字符串 evil 。请你返回 好字符串 的数目。 好字符串 的定义为&#x…

蓝桥杯刷题day05——2023

1、题目描述 请求出在12345678 (含) 至 98765432 (含) 中 &#xff0c;有多少个数中完全不包含 2023。 完全不包含 2023是指 无论将这个数的哪些数位移除都不能得到2023。 例如 20322175&#xff0c;33220022 都完全不包含 2023&#xff0c; 而20230415&#xff0c;20193213 …

C#如何实现一个输入框输入,匹配提示数据

在C#中可以使用AutoCompleteStringCollection类来实现输入框的自动完成功能。 首先需要创建一个包含所有候选项的字符串集合&#xff08;List&#xff09;或者从文件、数据库等地方获取到这些候选项。然后将该集合传递给TextBox控件的AutoCompleteCustomSource属性。 下面是一…

装饰你的APP:使用Lottie-Android创建动画效果

装饰你的APP&#xff1a;使用Lottie-Android创建动画效果 1. Lottie-Android简介 Lottie-Android是一个强大的开源库&#xff0c;由Airbnb开发&#xff0c;旨在帮助开发者轻松地在Android应用中添加高质量的动画效果。它基于Adobe After Effects软件中的Bodymovin插件&#x…

STM32的ADC采集传感器的模拟量数据

1、 由于项目上使用传感器采集数据&#xff0c;传感器可以输出模拟电压信号&#xff0c;但是模拟电压信号的输出范围是1-5V&#xff0c;而STM32的ADC采集电压范围是0-3.3V&#xff0c;此时可以用一个简单的分压电路将1-5V的电压将至0.5V到2.5V的范围。 2、电阻分压电路可以使用…

【Simulink系列】——动态系统仿真 之 离散系统线性离散系统

一、离散系统定义 离散系统是指系统的输入与输出仅在离散的时间上取值&#xff0c;而且离散的时间具有相同的时间间隔。满足下列条件&#xff1a; ①系统&#xff08;的输入输出&#xff09;每隔固定时间间隔才更新一次。固定时间间隔称为采样时间。 ②系统的输出依赖当前的…

2023年09月CCF-GESP编程能力等级认证Python编程三级真题解析

Python等级认证GESP(1~6级)全部真题・点这里 一、单选题(共15题,共30分) 第1题 人们所使用的手机上安装的App通常指的是( )。 A:一款操作系统 B:一款应用软件 C:一种通话设备 D:以上都不对 答案:B 第2题 下列流程图的输出结果是( )。 A:60 B:20 C:5 D…

倾斜摄影轻量化,这样才规范!

自然资源部发布了《倾斜数字摄影测量技术规程》等17项行业标准报批稿公示&#xff0c;其中高频出现的倾斜摄影技术&#xff0c;重回大众视野。 倾斜摄影技术是国际测绘领域近些年发展起来的一项高新技术&#xff0c;它颠覆了以往正射影像只能从垂直角度拍摄的局限&#xff0c;通…

栈--数据结构

初始化栈、入栈、出栈 栈&#xff1a;只允许在一端进行插入或删除操作的线性表 栈顶&#xff08;Top&#xff09; 代码 #include <stdio.h>#define MaxSize 50 typedef int ElemType; typedef struct {ElemType data[MaxSize];//数组int top;//始终指向栈顶的一个变量…

SparkStreaming---入门

文章目录 1.SparkStreaming简介1.1 流处理和批处理1.2 实时和离线1.3 SparkStreaming是什么1.4 SparkStreaming架构图 2.背压机制3.DStream案例实操 1.SparkStreaming简介 1.1 流处理和批处理 流处理和批处理是两种不同的数据处理方式&#xff0c;它们在处理数据的方式和特点…

【C++】类和对象之运算符重载(三)

前言&#xff1a;在前面我们知道在类和对象中有六个默认成员函数&#xff0c;并学习了其中三个构造函数、析构函数、拷贝构造函数&#xff0c;今天我们将进一步的学习.赋值运算符重载。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:高质…

Java并发基础:FutureTask全面解析!

内容概要 FutureTask结合了Future和Runnable接口&#xff0c;它能够异步执行任务&#xff0c;提高程序响应性&#xff0c;可以获取任务执行结果&#xff0c;并且支持任务取消机制&#xff0c;提高了灵活性&#xff0c;同时&#xff0c;它简化了并发编程&#xff0c;使多线程开…

【Linux系统 02】Shell脚本

目录 一、Shell概述 二、输入输出 三、分支控制 1. 表达式 2. if 分支 3. case 分支 四、循环控制 1. for 循环 2. while 循环 3. select 循环 五、函数 一、Shell概述 Shell是Linux系统连接用户和操作系统的外壳程序&#xff0c;将用户的输入和请求选择性传递给操…

Java中Object类常用的12个方法

前言 Java 中的 Object 方法在面试中是一个非常高频的点&#xff0c;毕竟 Object 是所有类的“老祖宗”。Java 中所有的类都有一个共同的祖先 Object 类&#xff0c;子类都会继承所有 Object 类中的 public 方法。 先看下 Object 的类结构&#xff1a; 1. getClass 方法 pub…

「悬浮捷径SoftCircle」安卓平台的hao123,一键打开万物

罗老师的onestep一步发布之前, 终端的打开形式还拘泥于桌面和负一屏 这种方式够简洁,但缺点明显: 1.入口单一性:只能在app首页和各种扫一扫之间选择和切换 2.操作复杂:入口切换需要频繁的进入退出桌面,步骤过于繁杂 以下是悬浮捷径SoftCircle的解决方式 1.入口的丰富性: 安卓平…

如何在飞凌嵌入式T113-i开发板的Buildroot中移植MQTT协议?

在实际的项目开发中&#xff0c;工程师朋友们可能会需要在文件系统中移植一些工具或协议&#xff0c;那么该如何进行移植操作呢&#xff1f; 我们可以通过添加package包配置的方式在OK113i-S开发板的Buildroot中移植新功能。本篇文章&#xff0c;小编就以在Buildroot移植MQTT协…

同构异机迁移方案2_目标服务器仅安装数据库软件scp物理文件

源端和目标端的数据库版本需要保持一致&#xff0c;补丁版本可以不一致&#xff0c;目标端磁盘空间不能小于源端空间&#xff0c;目标端只需要安装 Oracle 软件即可。 特别说明&#xff1a;本文档案例Oracle的安装路径不同&#xff0c;数据目录一致&#xff0c;采用scp的方式实…

关于Django部署

首先了解一下开发环境服务器跟生产环境服务器有何不同。 一、我们通过 python manage.py runserver 启动开发环境服务器&#xff0c;这条命令背后做了哪些事情&#xff1f; 1、首先加载Django项目的设置&#xff08;settings&#xff09; 2、检查数据库迁移&#xff0c;确保数…