今天在controller中写一个接口用来测试模拟多个请求同时到达 下订单的情况,
怎么能有效保证高并发下的库存和销量的一致性呢?【具体实现方法:https://www.cnblogs.com/sxdcgaq8080/p/9454161.html】
====
那么好,在这个接口中,开启多线程模拟了多个用户请求同时到达的状况,现在想在多个线程都执行完了以后再统一返回结果给前台,哪些请求成功了,哪些请求失败了。
====
所以现在的需求是怎么能实现 等待多个线程都执行完了以后再做事情~~~
===================================================================================================================================
其实想要实现这个需求:等待多个线程执行完了,再做事情。
有两种方法,可以应对不同的情况:
分别是CountDownLatch和CyclicBarrier
===================================================================================================================================
CountDownLatch和CyclicBarrier简单比较:
|
CountDownLatch |
CyclicBarrier |
---|---|---|
软件包 |
java.util.concurrent |
java.util.concurrent |
适用情景 |
主线程等待多个工作线程结束 |
多个线程之间互相等待,直到所有线程达到一个障碍点(Barrier point) |
主要方法 |
CountDownLatch(int count) (主线程调用) 初始化计数 CountDownLatch.await (主线程调用) 阻塞,直到等待计数为0解除阻塞 CountDownLatch.countDown 计数减一(工作线程调用) |
CyclicBarrier(int parties, Runnable barrierAction) //初始化参与者数量和障碍点执行Action,Action可选。由主线程初始化 CyclicBarrier.await() //由参与者调用 阻塞,直到所有线程达到屏障点 |
等待结束 |
各线程之间不再互相影响,可以继续做自己的事情。不再执行下一个目标工作。 |
在屏障点达到后,允许所有线程继续执行,达到下一个目标。可以重复使用CyclicBarrier |
异常 |
如果其中一个线程由于中断,错误,或超时导致永久离开屏障点,其他线程也将抛出异常。 |
|
其他 |
如果BarrierAction不依赖于任何Party中的所有线程,那么在任何party中的一个线程被释放的时候,可以直接运行这个Action。 If(barrier.await()==2) { //do action } |
CountDownLatch 使用示例代码:
主线程调用
工作线程调用
package com.sxd.swapping.utils; import org.junit.Test; import java.util.concurrent.CountDownLatch; public class ThreadTest { /** * 主线程 */ @Test public void test(){ //开启10个多线程 int threadCount = 10; //所有线程阻塞,然后统一开始 CountDownLatch begin = new CountDownLatch(1); //主线程阻塞,直到所有分线程执行完毕 CountDownLatch end = new CountDownLatch(threadCount); //开始多线程 begin.countDown(); for (Integer i = 0; i < threadCount; i++) { Runnable runnable = dealSomeThing(i,begin,end); new Thread(runnable).start(); } //多个线程都执行结束 try { end.await(); System.out.println("多个线程都执行结束,可以做自己的事情了"); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("多线程执行中出错了,凉凉了!!!"); } } /** * 工作线程 * 本方法 是在构造多线程要做的事情 * * =====================可以做的事=================== * 当然可以传入ConcurrentHashMap之类的线程安全的 类 * 来记录线程中的处理结果之类的 * 最后 在多线程都执行完了以后 就可以对处理结果进行操作了 * ================================================== * * @param threadNum 当前线程编号 * @param begin * @param end * @return */ private Runnable dealSomeThing(int threadNum, CountDownLatch begin, CountDownLatch end){ Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println("线程"+threadNum+":--------------------->开始工作"); begin.await(); System.out.println("线程"+threadNum+"做具体的事情,比如去service调用 具体的方法做什么操作之类的"); end.countDown(); System.out.println("线程"+threadNum+":--------------------->结束工作"); } catch (InterruptedException e) { e.printStackTrace(); } } }; return runnable; } }
最后实现的结果:
=========================================================================================