范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

19CountDownLatch和CyclicBarrier如何让多线程步调一致?

  前几天 老板突然过来说,系统对账越来越慢了,能不能优化下,业务过程还是很简单的,用户在商城下单,生产电子订单,保存在订单库。之后会生成物流派送订单,为了防止漏送或者重复派送还需要每天对账。
  对账系统的处理逻辑很简单,首先查询订单库,然后查询派送库,之后对比订单和派送订单,将差异写入差异库。
  核心代码经过抽象后,如下:  while(存在未对账订单){   // 查询未对账订单   pos = getPOrders();   // 查询派送单   dos = getDOrders();   // 执行对账操作   diff = check(pos, dos);   // 差异写入差异库   save(diff); } 利用并行优化对账系统
  要优化性能,首先要想到这个系统的瓶颈所在。
  目前的对账系统,由于订单量和派送单量巨大,所以查询未对账订单 getPOrders() 和查询派送单 getDOrders() 相对较慢,那有没有办法快速优化一下呢?目前对账系统是单线程执行的,图形化后是下图这个样子。对于串行化的系统,  优化性能首先想到的是能否利用多线程并行处理  。
  所以你可以看到这里对账系统的瓶颈。查询未对账订单 getPOrders() 和查询派送单 getDOrders() 是否可以并行处理呢?显然是可以的,因为这两个操作并没有先后顺序的依赖。这两个最耗时的操作并行之后,执行过程如下图所示。对比一下单线程的执行示意图,你会发现同等时间里,并行执行的吞吐量近乎单线程的 2 倍,优化效果还是相对明显的。
  思路有了,那么代码我们如何实现呢?我们创建了两个线程 T1 和 T2,并行执行查询未对账订单 getPOrders() 和查询派送单 getDOrders() 这两个操作。在主线程中执行对账操作 check() 和差异写入 save() 两个操作。不过需要注意的是:主线程需要等待线程 T1 和 T2 执行完才能执行 check() 和 save() 这两个操作,为此我们通过调用 T1.join() 和 T2.join() 来实现等待,当 T1 和 T2 线程退出时,调用 T1.join() 和 T2.join() 的主线程就会从阻塞态被唤醒,从而执行之后的 check() 和 save()。  while(存在未对账订单){   // 查询未对账订单   Thread T1 = new Thread(()->{     pos = getPOrders();   });   T1.start();   // 查询派送单   Thread T2 = new Thread(()->{     dos = getDOrders();   });   T2.start();   // 等待T1、T2结束   T1.join();   T2.join();   // 执行对账操作   diff = check(pos, dos);   // 差异写入差异库   save(diff); } 用 CountDownLatch 实现线程等待
  经过上面的优化,基本可以跟老板汇报工作了,但是还是有点不足,while循环里面每次都是创建新线程,而创建线程是个耗时的动作,所以最好就是创建好的线程循环使用,这是你估计想到线程池了,是的,线程池可以解决这个问题。
  下面的代码就是用线程池进行了优化:  // 创建2个线程的线程池 Executor executor =    Executors.newFixedThreadPool(2); while(存在未对账订单){   // 查询未对账订单   executor.execute(()-> {     pos = getPOrders();   });   // 查询派送单   executor.execute(()-> {     dos = getDOrders();   });      /* ??如何实现等待??*/      // 执行对账操作   diff = check(pos, dos);   // 差异写入差异库   save(diff); }
  前面线程通过调用线程t1 t2 join()方法来等待线程,但是在线程池里,线程根本就不会退出,所以join()方法失效了。那么如何解决这个问题呢?最直接的办法就是设置一个计数器,第一个操作完成计数器-1 ,第二个操作完成计数器-1 ,主线程等待计数器为 0 。等待计数器为0 其实就是一个条件变量,管程也可以实现。
  Java 中已经提供了类似的功能,  CountDownLatch  ,实现代码如下:  // 创建2个线程的线程池 Executor executor =    Executors.newFixedThreadPool(2); while(存在未对账订单){   // 计数器初始化为2   CountDownLatch latch =      new CountDownLatch(2);   // 查询未对账订单   executor.execute(()-> {     pos = getPOrders();     latch.countDown();   });   // 查询派送单   executor.execute(()-> {     dos = getDOrders();     latch.countDown();   });      // 等待两个查询操作结束   latch.await();      // 执行对账操作   diff = check(pos, dos);   // 差异写入差异库   save(diff); }进一步优化性能
  经过上面优化 长舒了一口气,终于可以交付了。那么还有没有其他可以优化的地方呢?仔细一看还是有的。
  前面我们只是把 两个查询操作并行了,那么check的动作是不是可以并行呢?当然了……
  对账的查询依赖于两次查询的结果,明显有点生产者 - 消费者的意思。为此 我们设计两个队列,一个订单队列,一个派送队列。
  下面再来看如何用双队列来实现完全的并行。一个最直接的想法是:一个线程 T1 执行订单的查询工作,一个线程 T2 执行派送单的查询工作,当线程 T1 和 T2 都各自生产完 1 条数据的时候,通知线程 T3 执行对账操作。这个想法虽看上去简单,但其实还隐藏着一个条件,那就是线程 T1 和线程 T2 的工作要步调一致,不能一个跑得太快,一个跑得太慢,只有这样才能做到各自生产完 1 条数据的时候,通知线程 T3。
  下面这幅图形象地描述了上面的意图:线程 T1 和线程 T2 只有都生产完 1 条数据的时候,才能一起向下执行,也就是说,线程 T1 和线程 T2 要互相等待,步调要一致;同时当线程 T1 和 T2 都生产完一条数据的时候,还要能够通知线程 T3 执行对账操作。
  用 CyclicBarrier 实现线程同步
  下面我们来实现以上方案,这个方案有两个难点,一个是 线程 T1 和 T2 要做到步调一致,另一个是要能够通知到线程 T3。
  同样,还是建议你不要在实际项目中这么做,因为 Java 并发包里也已经提供了相关的工具类:CyclicBarrier。在下面的代码中,我们首先创建了一个计数器初始值为 2 的 CyclicBarrier,你需要注意的是创建 CyclicBarrier 的时候,我们还传入了一个回调函数,当计数器减到 0 的时候,会调用这个回调函数。
  CountDownLatch 和 CyclicBarrier 是 Java 并发包提供的两个非常易用的线程同步工具类,这两个工具类用法的区别在这里还是有必要再强调一下:  CountDownLatch   主要用来解决一个线程等待多个线程的场景,可以类比旅游团团长要等待所有的游客到齐才能去下一个景点;而   CyclicBarrier 是一组线程之间互相等待  ,更像是几个驴友之间不离不弃。除此之外 CountDownLatch 的计数器是不能循环利用的,也就是说一旦计数器减到 0,再有线程调用 await(),该线程会直接通过。但 CyclicBarrier 的计数器是可以循环利用的,而且具备自动重置的功能,一旦计数器减到 0 会自动重置到你设置的初始值。除此之外,CyclicBarrier 还可以设置回调函数,可以说是功能丰富。
  本章的示例代码中有两处用到了线程池,你现在只需要大概了解即可,因为线程池相关的知识咱们专栏后面还会有详细介绍。另外,线程池提供了 Future 特性,我们也可以利用 Future 特性来实现线程之间的等待,这个后面我们也会详细介绍。

自驾游山东坦克陪伴安全呵护这次出行当然是开着我的爱车坦克了!先说爱车,出去玩避免不了走一些非铺装道路,固特ATT轮胎很好的保障了我的安全,合适的车一定有一双合适的鞋,以前的车胎噪很大,固特ATT轮胎很好的解LBL是什么?一篇看懂LOL世界赛前最大瓜2022电竞季因为世界赛开赛在即,LBL被迫提前进入休赛期,也就意味着近期英雄联盟最热门的话题也要暂时告一段落。什么?你还不知道LBL是什么?那胖哒就先给新来的各位朋友介绍一下LB世锦赛爆冷,日本战胜巴西,中国女排稳居小组第一北京时间9月30日晚,中国女排在世锦赛小组第四场比赛中战胜捷克,取得四连胜。同组另一场焦点战中,巴西女排以1比3负于日本女排,大爆冷门。本轮,中国女排以3比0战胜捷克,进而以四战全7577,内马尔地位提升,将改写51年格局,巴西祝贺,难超梅西导读从身缠疾病近5年每个赛季至少缺席40的比赛,到勇猛无匹进球如麻,内马尔的转变,令球迷感到喜悦,而要说这与世界杯的到来无关,恐怕球迷会嗤之以鼻。内马尔状态向好,意味着巴西更加难缠2场3球!5800万神锋给巴西出难题,孔蒂独具慧眼,热刺需他冲冠军在这次的国家队比赛日当中,排名世界第一的巴西分别进行了两场热身赛,面对加纳和突尼斯中,在内马尔的带领下,巴西先后以30和51横扫对手,在世界杯前就展现出不俗的状态。除了状态神勇的内声音伊藤美诚很开心赢下开门红,非常期待再次对决孙颖莎9月30日晚,成都世乒赛团体赛小组赛,日本女队以3比0击败了斯洛伐克队,拿到本届赛事的开门红。伊藤美诚出战第二场比赛,尽管在第三局4比11被对手击败,第四局也遇到了对手的顽强阻击,格里芬加盟凯尔特人,篮网签下盖茨,奇才签下多森北京时间10月1日,小编先在这里祝大家国庆节快乐!NBA休赛期正在进行,但联盟依然热闹非凡,各种交易传闻满天飞,就在刚刚,据名记JDShaw报道,布鲁克林篮网已经签下了自由球员前锋油价调整消息国庆节油价大跌!10月1日国内9295号汽油调后价油价调整消息国庆节油价大跌,10月1日国内9295号汽油调后价今天是2022年10月1日,星期六!刚结束的9月油价迎来一涨一跌,10月的油价走势如何呢?新一轮油价将于10号24时正S12入围赛RNG01DRX首战告负,如何评价这场比赛?对面先选了芮尔,为了好打芮尔第五选选了牛头,结果对面前期不跟你打,牛头的作用没发挥出来RNG完全低估了大树这个英雄的作用,大树在打野位置最大的缺点是抓人能力不行,W距离太短,R作为03!英格兰创29年耻辱,坐拥13亿的豪阵,世界杯出线却悬了英格兰踢完了6轮欧国联比赛,索斯盖特的球队未尝一胜,排名垫底,并且提前降级。此前,英格兰踢出了04的比分,输给了匈牙利,被对手双杀。面对意大利,英格兰则是01输球。上一场欧国联,对或将断绝父子关系,儿媳自曝婆媳不和后,贝克汉姆愤怒警告长子9月30日,据外媒报道,儿媳妮可拉佩尔茨受访时承认婆媳不和的行为令贝克汉姆夫妇非常震惊,夫妻俩几乎是悲痛欲绝,差点被摧毁。因为不堪被骂恶婆婆,目前,维多利亚的社交账号已经关闭了评论
四强出炉!中国金花苦战三盘惜败,郑钦文领先被逆转,发球成短板2022年8月13日,WTA多伦多站的比赛继续进行,四强全部诞生,中国金花郑钦文高开低走,10领先连丢两盘,最终12输给捷克名将卡。普利斯科娃,遭到对手逆转,发球成短板。中国金花郑中国名将40横扫斯诺克女皇,张健康轻松晋级北京时间8月13日消息,2021年斯诺克英国公开赛资格赛继续进行。一场焦点比赛中,中国名将张健康发挥出色,40轻取斯诺克女皇瑞恩埃文斯。稍早前,中国一哥丁俊晖以42战胜小莱恩斯,正男排队长拒绝参加世锦赛,抱怨国家队待遇太差,直言奖金给少了现如今,世界各大强队都在盯着接下来的世锦赛,相比起女排世锦赛来说,男排世锦赛更是迫在眉睫,这个月底将展开激烈竞逐,因此各大参赛球队都在积极投入备战,中国男排尽管目前正在参加亚洲杯赛郭艾伦离队倒计时,四支球队将成下家,加盟北京首钢再也不怕裁判南下投奔老叔打造第二支辽宁队。郭艾伦现在的态度是非常明确,恨不得是立马上能够脱离辽宁队,看得出对于辽宁队郭艾伦是没有任何留恋之前,郭艾伦一旦离队,最好的归宿莫过于南下投奔老叔郭士强33岁巴特勒变肉筋人!乔丹接班人,NBA铁血硬汉,不缺白富美NBA属于全世界顶级篮球赛事,这个联盟从来不缺乏有天赋的球星,因此每年夏天就算是NBA超巨也不敢松懈。作为热火队的老大领袖,33岁的巴特勒在这个夏天坚持苦练,各方面状态不仅没有下滑前轻量级三冠王洛佩兹称重结束,正式登陆140磅,能残暴KO对手吗文搏击江湖北京时间8月14日,世界拳坛将迎来一场重要比赛,前轻量级三冠王特奥菲莫洛佩兹主场迎战墨西哥人佩德罗坎帕,今天,两人已经进行了赛前称重。坎帕的称重结果为139磅,洛佩兹的称女单世界冠军大获全胜!41淘汰日本选手,次轮迎战日本伊藤美诚北京时间8月13日,日本乒协巴黎奥运会选拔赛正在进行。本次选拔赛,女单方面多达24人报名参赛,刚刚结束的比赛中,日本世界冠军石川佳纯大获全胜,总比分41击败对手南波侑里香,成功晋级2022年换机参考真我GT2大师探索版,续航性能天花板,好用不贵真我GT2大师探索版这次采用了骁龙8gen1处理器外加5000毫安超大电池,可以说这是现阶段同时兼顾性能与续航的完美组合。不过续航这东西还是得亲身试验一下,下面就由小编来为大家带来PHP环境搭建教程PHP是一种编程语言,很多网站都用PHP语言编写,我们有时候需要测试一个网站,就需要PHP环境才能运行,又要安装Apache又要安装MySQL真的非常麻烦。其实我们可以使用PHP集有张有驰,才是生命正确的节奏生活中太多人习惯这样想问题如果自己得到那个工作,如果有了那个房子,如果赚到了那样多的钱就会觉得幸福和满足。可事实上,一旦开启追逐的脚步,就很难停下来,现实中根本没有那么多那个。从一以为很熟悉CountDownLatch的使用了,没想到在生产环境翻车了前言大家好,我是小郭,之前分享了CountDownLatch的使用,我们知道用来控制并发流程的同步工具,主要的作用是为了等待多个线程同时完成任务后,在进行主线程任务。万万没想到,在