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

2024-02-04 12:52

本文主要是介绍多线程例子,通过启动三个线程 等三个线程都跑完后打印结果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

需求描述:开启一个多线程跑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.chinasem.cn/article/677580

相关文章

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

Java中常见队列举例详解(非线程安全)

《Java中常见队列举例详解(非线程安全)》队列用于模拟队列这种数据结构,队列通常是指先进先出的容器,:本文主要介绍Java中常见队列(非线程安全)的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一.队列定义 二.常见接口 三.常见实现类3.1 ArrayDeque3.1.1 实现原理3.1.2

SpringBoot3中使用虚拟线程的完整步骤

《SpringBoot3中使用虚拟线程的完整步骤》在SpringBoot3中使用Java21+的虚拟线程(VirtualThreads)可以显著提升I/O密集型应用的并发能力,这篇文章为大家介绍了详细... 目录1. 环境准备2. 配置虚拟线程方式一:全局启用虚拟线程(Tomcat/Jetty)方式二:异步

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、