之前遇到了这么一个需求
一个同步的请求,每次请过过来我需要调用底层接口创建配置文件,需要创建4个配置文件
但是这个接口有点慢,每个接口大概1.5S,4个接口6S对一个同步接口显然是不能接受的
我创建成功之后还要回调service的接口
之前遇到这个问题确实难道了我半天,然后去了解了多线程和计数器
首先创建计数器多线程同时跑4个接口调用计数器到4时候在回调接口Java线程会议如下三种方式结束,结束后就处于死亡状态
run()或者call()方法执行完成,线程正常结束;线程抛出一个未捕获的Exception或Error;直接调用该线程的stop()方法来结束该线程; 所以要捕获异常防止线程异常结束,导致计数器长期阻塞准备工作
//模拟回调接口 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); } }