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

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

相关文章

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

RabbitMQ消费端单线程与多线程案例讲解

《RabbitMQ消费端单线程与多线程案例讲解》文章解析RabbitMQ消费端单线程与多线程处理机制,说明concurrency控制消费者数量,max-concurrency控制最大线程数,prefe... 目录 一、基础概念详细解释:举个例子:✅ 单消费者 + 单线程消费❌ 单消费者 + 多线程消费❌ 多

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

Java中的xxl-job调度器线程池工作机制

《Java中的xxl-job调度器线程池工作机制》xxl-job通过快慢线程池分离短时与长时任务,动态降级超时任务至慢池,结合异步触发和资源隔离机制,提升高频调度的性能与稳定性,支撑高并发场景下的可靠... 目录⚙️ 一、调度器线程池的核心设计 二、线程池的工作流程 三、线程池配置参数与优化 四、总结:线程

WinForm跨线程访问UI及UI卡死的解决方案

《WinForm跨线程访问UI及UI卡死的解决方案》在WinForm开发过程中,跨线程访问UI控件和界面卡死是常见的技术难题,由于Windows窗体应用程序的UI控件默认只能在主线程(UI线程)上操作... 目录前言正文案例1:直接线程操作(无UI访问)案例2:BeginInvoke访问UI(错误用法)案例

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab