java子线程并发处理多个业务后同步到主线程统一返回


一、业务场景

1.需求

并发多个不同的业务,将所有业务的执行结果汇总返回,每个业务的需求时间不定,汇总返回耗时不能超过5秒(超时未返回结果的业务放弃)

2.分析

Thread 和 Runnable 不能返回结果,Callable 虽然可以返回子线程的结果,但是一旦调用get后就变成顺序执行而不是并发,Spring的MQ是异步并发的但是好像不能汇总结果,找了半天没找到现成的,所以就想着自己写一个吧。


二、实现方法

Thread 实现并发,synchronized 同步返回结果

1.统一业务返回格式

//返回数据的结构
@Data
class Res {
    private String name;                    // 业务名称
    private Integer code;                    // 状态码
    private String errMsg;                  // 报错信息
    private ArrayList<String> dataList;     // 返回数据
}

2.创建数据缓冲区

// 数据缓冲区
class SynContainer {

    // 业务执行结果汇总
    ArrayList<Res> sList = new ArrayList<>();
    // 业务执行完毕提交方法【同步锁】
    public synchronized void submit(Res res) {
        sList.add(res);
    }

}

3.创建业务

// 业务线程1
class Service1 extends Thread{
    SynContainer container;

    public Service1(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {

        // 业务内容【自定义】 ------------------------------
        // 模拟耗时200毫秒
        try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}
        // 模拟返回数据
        ArrayList<String> s = new ArrayList<>();
        s.add("数据1");
        s.add("数据2");
        s.add("数据3");
        s.add("数据4");
        Res r = new Res();
        r.setName("业务1");
        r.setCode(200);
        r.setErrMsg("请求成功");
        r.setDataList(s);
        container.submit(r);
        System.out.println("业务1执行完毕");
        // ----------------------------------------------

    }

}

// 业务线程2
class Service2 extends Thread{
    SynContainer container;

    public Service2(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {

        // 业务内容【自定义】 ------------------------------
        // 模拟耗时200毫秒
        try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}
        // 模拟返回数据
        ArrayList<String> s = new ArrayList<>();
        s.add("数据1");
        s.add("数据2");
        s.add("数据3");
        s.add("数据4");
        Res r = new Res();
        r.setName("业务2");
        r.setCode(200);
        r.setErrMsg("请求成功");
        r.setDataList(s);
        container.submit(r);
        System.out.println("业务2执行完毕");
        // ----------------------------------------------

    }

}

4.创建计时器

// 计时器
class Timer {

    private Date startTime;
    private final long during;

    public Timer(long during) {
        this.during = during;
    }

    public void start() {
        this.startTime = new Date();
    }

    public Boolean isTimeOver() {
        Date now = new Date();
        long t = now.getTime() - this.startTime.getTime();

        return t>=during;
    }

}

5.创建执行类

// 执行类
class Executor {

    private final ArrayList<Thread> tList;     // 业务队列
    private final SynContainer container;      // 数据缓冲区
    private final long during;                 // 最大等待时间

    public Executor(ArrayList<Thread> tList, SynContainer container, long during) {
        this.tList = tList;
        this.container = container;
        this.during = during;
    }

    public ArrayList<Res> run() {
        
        // 启动业务 -------------------------------------
        for(Thread service: this.tList) service.start();
        // ---------------------------------------------

        // 初始化计时器 --------------------
        Timer tm = new Timer(this.during);
        tm.start();
        // -------------------------------

        // 线程状态监控【如果全部线程都执行完成 或者 未全部执行完成但总耗时超过了最大等待时间,就结束等待】-----
        for(Thread service: this.tList) {
            Thread.State state = service.getState();
            while (state != Thread.State.TERMINATED && !tm.isTimeOver()) {

                state = service.getState();
                System.out.println("当前线程状态:" + state);

                try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

            }
        }
        // ------------------------------------------------------------------------------------

        // 汇总返回结果
        return this.container.sList;
    }

}

6.创建入口函数

public class MyThread {

    public static void main(String[] args) {

        // 初始化缓冲区
        SynContainer container = new SynContainer();

        // 创建业务队列
        ArrayList<Thread> tList = new ArrayList<>();
        tList.add(new Service1(container));
        tList.add(new Service2(container));

        // 最大等待时长
        long during = 5000;

        // 执行业务 汇总返回
        ArrayList<Res> rList = new Executor(tList, container, during).run();
        System.out.println(rList);

    }

}

三、执行结果

在这里插入图片描述

ps:如有更好的实现方法希望大神指正(旺柴)


  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什么都干的派森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值