当前位置: 首页 > news >正文

建站宝盒站群版南京seo圈子

建站宝盒站群版,南京seo圈子,做帖子网站,seo关键词排名优化怎么样📝个人主页:五敷有你 🔥系列专栏:并发编程 ⛺️稳中求进,晒太阳 CountDownLatch 概念 CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。 CountDownLatch 定义了一个计数器,…

       📝个人主页:五敷有你      

 🔥系列专栏:并发编程

⛺️稳中求进,晒太阳

CountDownLatch 概念

CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。

CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列所有线程,这里的计数器是一个标志,可以表示一个任务一个线程,也可以表示一个倒计时器,CountDownLatch可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。

CountDownLatch 常用方法说明

CountDownLatch(int count); //构造方法,创建一个值为count 的计数器。 ​ await();//阻塞当前线程,将当前线程加入阻塞队列。 ​ await(long timeout, TimeUnit unit);//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行, ​ countDown();//对计数器进行递减1操作,当计数器递减至0时,当前线程会去唤醒阻塞队列里的所有线程。

用CountDownLatch 来优化我们的报表统计

功能现状

运营系统有统计报表、业务为统计每日的用户新增数量、订单数量、商品的总销量、总销售额......等多项指标统一展示出来,因为数据量比较大,统计指标涉及到的业务范围也比较多,所以这个统计报表的页面一直加载很慢,所以需要对统计报表这块性能需进行优化。

问题分析

统计报表页面涉及到的统计指标数据比较多,每个指标需要单独的去查询统计数据库数据,单个指标只要几秒钟,但是页面的指标有10多个,所以整体下来页面渲染需要将近一分钟。

解决方案

任务时间长是因为统计指标多,而且指标是串行的方式去进行统计的,我们只需要考虑把这些指标从串行化的执行方式改成并行的执行方式,那么整个页面的时间的渲染时间就会大大的缩短, 如何让多个线程同步的执行任务,我们这里考虑使用多线程,每个查询任务单独创建一个线程去执行,这样每个统计指标就可以并行的处理了。

要求

因为主线程需要每个线程的统计结果进行聚合,然后返回给前端渲染,所以这里需要提供一种机制让主线程等所有的子线程都执行完之后再对每个线程统计的指标进行聚合。 这里我们使用CountDownLatch 来完成此功能。

模拟代码

1、分别统计4个指标用户新增数量、订单数量、商品的总销量、总销售额;

2、假设每个指标执行时间为3秒。如果是串行化的统计方式那么总执行时间会为12秒。

3、我们这里使用多线程并行,开启4个子线程分别进行统计

4、主线程等待4个子线程都执行完毕之后,返回结果给前端。

​//用于聚合所有的统计指标private static Map map=new HashMap();//创建计数器,这里需要统计4个指标private static CountDownLatch countDownLatch=new CountDownLatch(4);
​public static void main(String[] args) {
​//记录开始时间long startTime=System.currentTimeMillis();
​Thread countUserThread=new Thread(new Runnable() {public void run() {try {System.out.println("正在统计新增用户数量");Thread.sleep(3000);//任务执行需要3秒map.put("userNumber",1);//保存结果值countDownLatch.countDown();//标记已经完成一个任务System.out.println("统计新增用户数量完毕");} catch (InterruptedException e) {e.printStackTrace();}
​}});Thread countOrderThread=new Thread(new Runnable() {public void run() {try {System.out.println("正在统计订单数量");Thread.sleep(3000);//任务执行需要3秒map.put("countOrder",2);//保存结果值countDownLatch.countDown();//标记已经完成一个任务System.out.println("统计订单数量完毕");} catch (InterruptedException e) {e.printStackTrace();}
​}});
​Thread countGoodsThread=new Thread(new Runnable() {public void run() {try {System.out.println("正在商品销量");Thread.sleep(3000);//任务执行需要3秒map.put("countGoods",3);//保存结果值countDownLatch.countDown();//标记已经完成一个任务System.out.println("统计商品销量完毕");} catch (InterruptedException e) {e.printStackTrace();}
​}});
​Thread countmoneyThread=new Thread(new Runnable() {public void run() {try {System.out.println("正在总销售额");Thread.sleep(3000);//任务执行需要3秒map.put("countmoney",4);//保存结果值countDownLatch.countDown();//标记已经完成一个任务System.out.println("统计销售额完毕");} catch (InterruptedException e) {e.printStackTrace();}
​}});//启动子线程执行任务countUserThread.start();countGoodsThread.start();countOrderThread.start();countmoneyThread.start();
​try {//主线程等待所有统计指标执行完毕countDownLatch.await();long endTime=System.currentTimeMillis();//记录结束时间System.out.println("------统计指标全部完成--------");System.out.println("统计结果为:"+map.toString());System.out.println("任务总执行时间为"+(endTime-startTime)/1000+"秒");
​} catch (InterruptedException e) {e.printStackTrace();}
​
​}
​

执行结果

CountDownLatch实现原理

1、创建计数器

当我们调用CountDownLatch countDownLatch=new CountDownLatch(4) 时候,此时会创建一个AQS的同步队列,并把创建CountDownLatch 传进来的计数器赋值给AQS队列的 state,所以state的值也代表CountDownLatch所剩余的计数次数;

  public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count);//创建同步队列,并设置初始计数器值}

2、阻塞线程

当我们调用countDownLatch.wait()的时候,会创建一个节点,加入到AQS阻塞队列,并同时把当前线程挂起。

  public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1);}

判断计数器是技术完毕,未完毕则把当前线程加入阻塞队列

  public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();//锁重入次数大于0 则新建节点加入阻塞队列,挂起当前线程if (tryAcquireShared(arg) < 0)doAcquireSharedInterruptibly(arg);}

构建阻塞队列的双向链表,挂起当前线程

 private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {//新建节点加入阻塞队列final Node node = addWaiter(Node.SHARED);boolean failed = true;try {for (;;) {//获得当前节点pre节点final Node p = node.predecessor();if (p == head) {int r = tryAcquireShared(arg);//返回锁的stateif (r >= 0) {setHeadAndPropagate(node, r);p.next = null; // help GCfailed = false;return;}}//重组双向链表,清空无效节点,挂起当前线程if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}

3、计数器递减

当我们调用countDownLatch.down()方法的时候,会对计数器进行减1操作,AQS内部是通过释放锁的方式,对state进行减1操作,当state=0的时候证明计数器已经递减完毕,此时会将AQS阻塞队列里的节点线程全部唤醒。

http://www.hkea.cn/news/400122/

相关文章:

  • 网站建设的一些问题友链交易交易平台
  • 创业初期要建立公司的网站吗seo排名优化代理
  • 做网站全屏尺寸是多少钱站长工具查询系统
  • 做企业平台的网站有哪些手机网站制作教程
  • 免费行情的软件大全下载北京公司排名seo
  • 网站联系方式要素qq群推广链接
  • div css 网站模板免费的云服务器有哪些
  • 35互联做网站好吗网店运营工作内容
  • 网站建设模拟软件营销培训课程内容
  • 深圳建网站兴田德润专业2023年最新新闻简短摘抄
  • 学校网站怎么查询录取百度相册登录入口
  • 自助建设彩票网站网址查询工具
  • 怎么创建网页的快捷方式seo入门版
  • 互联网企业网站网络优化
  • 山东手工活外发加工网四川二级站seo整站优化排名
  • 行业门户网站开发百度竞价怎么做效果好
  • 适合前端做项目的网站百度网盘搜索
  • 下载网站怎么下载广州网站定制多少钱
  • 西安攻略旅游自由行怎么玩北京seo软件
  • 汉川网站建设sem代运营
  • 装酷网装修平台东莞seo外包
  • 专门做图片的网站吗如何建网站要什么条件
  • 卢氏县住房和城乡建设局网站站长统计 站长统计
  • 济南 网站制作旺道营销软件
  • 新上线网站如何做搜索引擎站长素材网站
  • 做网站编辑深圳疫情防控最新消息
  • PHP网站开发项目式教程google下载手机版
  • 国外专门用于做网站图片的做网站要多少钱
  • 网站维护费用计入什么科目媒介星软文平台官网
  • 网站建设seo 视频做网站哪个平台好