同步方法内调用多个有延迟接口解决方案

需求介绍

在这里插入图片描述
之前遇到了这么一个需求

一个同步的请求,每次请过过来我需要调用底层接口创建配置文件,需要创建4个配置文件

但是这个接口有点慢,每个接口大概1.5S,4个接口6S对一个同步接口显然是不能接受的

我创建成功之后还要回调service的接口

思路

之前遇到这个问题确实难道了我半天,然后去了解了多线程和计数器

  1. 首先创建计数器
  2. 多线程同时跑4个接口调用
  3. 计数器到4时候在回调接口

Java线程会议如下三种方式结束,结束后就处于死亡状态

  1. run()或者call()方法执行完成,线程正常结束;
  2. 线程抛出一个未捕获的Exception或Error;
  3. 直接调用该线程的stop()方法来结束该线程;
    所以要捕获异常防止线程异常结束,导致计数器长期阻塞

code

准备工作

//模拟回调接口
public class CallBack {
    public static void callBack(){
        System.out.println("callBack");
    }
}
import java.util.concurrent.TimeUnit;
//模拟创建文件接口
public class HttpMock {
    public static void createA() throws Exception {
        //模拟等待
        TimeUnit.SECONDS.sleep(2);
        System.out.println("createA");
    }

    public static void createB() throws Exception {
        TimeUnit.SECONDS.sleep(2);
        System.out.println("createB");
    }

    public static void createC() throws Exception {
        TimeUnit.SECONDS.sleep(2);
        System.out.println("createC");
    }

    public static void createD() throws Exception {
        TimeUnit.SECONDS.sleep(2);
        System.out.println("createD fail");
        throw new RuntimeException();
    }
}
import java.util.concurrent.*;
//线程池。不要用Executors去创建,可能会出问题的
public class ThreadPoolUtil {
    private static volatile ExecutorService threadPool;

    public static ExecutorService getThreadPool(){
        synchronized (ThreadPoolUtil.class){
            if(threadPool == null || threadPool.isShutdown()){
                synchronized (ThreadPoolUtil.class){
                    customThreadPool();
                }
            }
            return threadPool;
        }
    }

    private static void customThreadPool() {
         threadPool =
                new ThreadPoolExecutor(0,
                        5,
                        1L,
                        TimeUnit.SECONDS,
                        new LinkedBlockingQueue<>(3),
                        Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.DiscardOldestPolicy()
                );
    }
}
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;

public class Demo {

    public Boolean test(Integer id ) {
        CountDownLatch countDownLatch = new CountDownLatch(4);
        //多线程操作集合类,不能用hashset,这里我也想过用atomic,不过想想还是set比较好
        CopyOnWriteArraySet copyOnWriteArraySet = new CopyOnWriteArraySet();

        //在项目里我也是全部try catch 而且HTTP设置了超时时间
        //防止这个线程死了,整个计数器都执行不下去
        ThreadPoolUtil.getThreadPool().execute(() -> {
            try {
                HttpMock.createA();
            }catch (Exception e) {
                e.printStackTrace();
                //把A放到集合里,一会落库,这条失败了
                //应该是枚举,但是我这个案列就不写那么详细了
                copyOnWriteArraySet.add("A");
            }
            countDownLatch.countDown();
        });

        ThreadPoolUtil.getThreadPool().execute(() -> {
            try {
                HttpMock.createB();
            } catch (Exception e) {
                e.printStackTrace();
                copyOnWriteArraySet.add("B");
            }
            countDownLatch.countDown();
        });

        ThreadPoolUtil.getThreadPool().execute(() -> {
            try {
                HttpMock.createC();
            } catch (Exception e) {
                e.printStackTrace();
                copyOnWriteArraySet.add("C");
            }
            countDownLatch.countDown();
        });

        ThreadPoolUtil.getThreadPool().execute(() -> {
            try {
                HttpMock.createD();
            } catch (Exception e) {
                e.printStackTrace();
                copyOnWriteArraySet.add("D");
            }
            countDownLatch.countDown();
        });

        //主线程等待
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if(copyOnWriteArraySet.isEmpty()){
            CallBack.callBack();
            System.out.println("this is ok");
            return true;
        }
        System.out.println("this is fail");
        //把集合的数据加上id落库,我们还要做一些处理,你可以选择删除或者其他一些操作
        return false;
    }

    public static void main(String[] args) {
        new Demo().test(1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

orange大数据技术探索者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值