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

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

相关文章

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

Windows设置nginx启动端口的方法

《Windows设置nginx启动端口的方法》在服务器配置与开发过程中,nginx作为一款高效的HTTP和反向代理服务器,被广泛应用,而在Windows系统中,合理设置nginx的启动端口,是确保其正... 目录一、为什么要设置 nginx 启动端口二、设置步骤三、常见问题及解决一、为什么要设置 nginx

springboot启动流程过程

《springboot启动流程过程》SpringBoot简化了Spring框架的使用,通过创建`SpringApplication`对象,判断应用类型并设置初始化器和监听器,在`run`方法中,读取配... 目录springboot启动流程springboot程序启动入口1.创建SpringApplicat

树莓派启动python的实现方法

《树莓派启动python的实现方法》本文主要介绍了树莓派启动python的实现方法,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、RASPBerry系统设置二、使用sandroidsh连接上开发板Raspberry Pi三、运

异步线程traceId如何实现传递

《异步线程traceId如何实现传递》文章介绍了如何在异步请求中传递traceId,通过重写ThreadPoolTaskExecutor的方法和实现TaskDecorator接口来增强线程池,确保异步... 目录前言重写ThreadPoolTaskExecutor中方法线程池增强总结前言在日常问题排查中,

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可