专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

老司机发车了,CountDownLatch到底等不等你呀

  前几天我们把ReentrantLock的原理进行了详细的讲解,不熟悉的同学可以翻看前文,今天我们介绍另一种基于AQS的同步工具CountDownLatch。
  CountDownLatch被称为倒计时器,也叫闭锁,是juc包下的工具类,同时也是共享锁的一种实现。它的作用是可以让一个或多个线程等待,直到所有线程的任务都执行完之后再继续往下执行。
  举个简单的例子:阿Q高中时期都是乘坐大巴往返于县城与农村,那时的司机为了利益的最大化,会在汽车满员的情况下才会发车。
  如果我们把乘客去车站乘车比作一个一个的线程,那CountDownLatch做的事就是等大家到齐之前的等待工作。
  我们从源码的角度来分析下它的工作原理
  谁来决定公交车上的座位数?
  公交车上的座位数是由汽车制造商决定的,在CountDownLatch中也会存在这样一个值count,用来表示需要等待的线程个数。
  count值是在CountDownLatch的构造函数中进行初始化的publicCountDownLatch(intcount){if(count0)thrownewIllegalArgumentException(count0);this。syncnewSync(count);}Sync(intcount){设置AQS中的state为count值setState(count);}
  计数值count是一次性的,当它的值减为0后就不会再变化了,这也是其存在的不足之处。
  谁来确定乘客全部到齐?
  在汽车发车前检票员会对车上的乘客数量进行清点,如果满员了就会通知司机开车。
  当然也可以采用这种方法:在得知车座位数的前提下,每上来一位乘客,座位数进行减一操作。CountDownLatch就是采用的上述方法,它的countDown()方法会对state的值执行减1操作。
  让我们从源码的角度来认识一下该方法。publicvoidcountDown(){释放共享锁sync。releaseShared(1);}publicfinalbooleanreleaseShared(intarg){if(tryReleaseShared(arg)){doReleaseShared();returntrue;}returnfalse;}
  先尝试释放锁,如果返回true,则执行释放操作,反之不执行。我们分析下上边的两个方法protectedbooleantryReleaseShared(intreleases){for(;;){获取当前等待的线程数量intcgetState();等待线程数为0,表示没有等待线程,故不需要释放锁资源if(c0)returnfalse;执行减1操作intnextcc1;自旋CAS将state的属性值1if(compareAndSetState(c,nextc))returnnextc0;}}
  最后一步中,如果减一之后为0,则说明没有其它线程等待,需要执行释放锁操作,返回true,反之不需要。
  在开始分析doReleaseShared()之前,我们先来补全一下AQS中waitStatus的状态说明初始化状态:0,表示当前节点在同步队列中,等待获取锁;CANCELLED:1,表示当前节点取消获取锁;SIGNAL:1,表示后续节点等待当前节点唤醒;CONDITION:2,表示当前线程正在条件等待队列中;PROPAGATE:3,共享模式,前置节点唤醒后续节点后,唤醒操作无条件传播下去;释放锁:唤醒后续节点privatevoiddoReleaseShared(){for(;;){Nodehhead;不是null且不为尾节点,因为尾节点没有后续节点需要唤醒了if(h!nullh!tail){intwsh。waitStatus;只有状态为1才可以唤醒后续节点if(wsNode。SIGNAL){将waitStatus设置为0失败会继续循环if(!compareAndSetWaitStatus(h,Node。SIGNAL,0))continue;unparkSuccessor(h);}将waitStatus设置为PROPAGATE失败会继续循环elseif(ws0!compareAndSetWaitStatus(h,0,Node。PROPAGATE))continue;}if(hhead)break;}}
  unparkSuccessor()方法用于唤醒AQS中被挂起的线程,在ReentrantLock的原理中讲过了,此处不再赘述。
  小结:当线程使用countDown()方法时,其实是使用了tryReleaseShared()方法以CAS的操作来减少state,直至state为0,进而释放锁资源,唤醒后续节点。
  谁来发车?
  肯定是司机来发车呀,那我们的CountDownLatch是如何实现的呢?
  CountDownLatch中的await()方法,就是等待线程的总开关,当发现state的值为0时会释放所有的等待线程,发车了。
  我们从源码角度来看下它是如何工作的publicvoidawait()throwsInterruptedException{sync。acquireSharedInterruptibly(1);}publicfinalvoidacquireSharedInterruptibly(intarg)throwsInterruptedException{如果线程中断了,直接抛出中断异常if(Thread。interrupted())thrownewInterruptedException();如果小于0,代表state不为0,即还有任务未执行完毕,会执行获取共享锁的操作if(tryAcquireShared(arg)0)doAcquireSharedInterruptibly(arg);}protectedinttryAcquireShared(intacquires){return(getState()0)?1:1;}
  我们来看看它到底是如何获取共享锁的privatevoiddoAcquireSharedInterruptibly(intarg)throwsInterruptedException{将当前线程封装成node放到队尾finalNodenodeaddWaiter(Node。SHARED);booleanfailedtrue;try{for(;;){finalNodepnode。predecessor();if(phead){intrtryAcquireShared(arg);state为0,表示此时等待线程全部执行完毕,r为1。if(r0){setHeadAndPropagate(node,r);p。nextnull;failedfalse;return;}}从当前node节点向前寻找有效节点,并保证有效节点的waitStatus状态为1if(shouldParkAfterFailedAcquire(p,node)挂起线程parkAndCheckInterrupt())在拿锁的期间,如果被中断了,那么会抛出异常,取消拿锁thrownewInterruptedException();}}finally{if(failed)将当前节点设置为失效节点,并挂到最近的有效节点后边,上文中有图解cancelAcquire(node);}}
  其中最重要的就是setHeadAndPropagate()方法privatevoidsetHeadAndPropagate(Nodenode,intpropagate){Nodehhead;将当前node设置为head,并将node的线程置为空setHead(node);if(propagate0hnullh。waitStatus0(hhead)nullh。waitStatus0){Nodesnode。next;if(snulls。isShared())释放锁:唤醒后续节点doReleaseShared();}}
  小结:当线程使用await()方法时会将当前线程封装成node加入AQS队列中,如果发现state不为0,说明还有任务未执行完成,继续阻塞;如果state为0,会释放掉所有的等待线程,执行await()之后的数据。
  流程图了解一下
  理论讲完了,那我们用代码来演示下上边的例子publicstaticvoidmain(String〔〕args)throwsInterruptedException{intcount10;设置线程池并发数ExecutorServiceexecutorServiceExecutors。newFixedThreadPool(count);假设大巴可以拉十个乘客,初始化stateCountDownLatchcountDownLatchnewCountDownLatch(count);for(inti0;icount;i){finalintnumi;executorService。execute((){try{Thread。sleep((long)(newRandom()。nextDouble()3000)1000);System。out。println(乘客坐在了(num1)号座位上);}catch(InterruptedExceptionexception){exception。printStackTrace();}finally{countDownLatch。countDown();}});}System。out。println(司机等待乘客上车);countDownLatch。await();System。out。println(发车了);executorService。shutdown();}
  执行结果如下:
  细心地同学肯定会问了:如果遇上刮风下雨,来坐车的人少了,那已经上车的乘客岂不是回不了家了?
  当然不是了,大巴其实也是有时间观念的,即使车上的乘客不满员到了一定的时间司机也会发车的,另外还会在路上顺道稍几个人上车。那我们的CountDownLatch是如何实现的呢?
  CountDownLatch还提供了一个await(longtimeout,TimeUnitunit)方法,在一定的时间间隔内会阻塞当前线程,等待count个线程执行任务,一旦超出了等待时间,便会继续往下执行。
  我们将上边的countDownLatch。await();替换为countDownLatch。await(3,TimeUnit。SECONDS);,执行结果如下所示
  上文中的例子是CountDownLatch的其中一种用法,即主线程等待其他线程执行完毕之后再执行。它还有另一种用法,即实现多个线程开始执行任务的最大并行性,类似发令枪响前,运动员统一在起跑线就位的场景。publicstaticvoidmain(String〔〕args)throwsInterruptedException{设置线程池并发数ExecutorServiceexecutorServiceExecutors。newFixedThreadPool(10);CountDownLatchcountDownLatchnewCountDownLatch(1);一组有6名运动员for(inti0;i6;i){finalintnumi;executorService。execute((){try{System。out。println(运动员(num1)等待发令枪响);countDownLatch。await();System。out。println(运动员(num1)开始起跑);}catch(InterruptedExceptionexception){exception。printStackTrace();}});}Thread。sleep(3000);countDownLatch。countDown();System。out。println(发令枪响);executorService。shutdown();}
  执行结果如下
  说了这么多,都是样例?你有没有在项目中应用过呢?
  回答当然是Yes了,之前的运营端有个统计页面,要求统计用户新增数量、订单数量、商品交易总额等多张表的指标值,为了提高执行速率,我就启用了多个子线程分别去统计,用CountDownLatch来等待它们的统计结果。

华为18级牛人3个月肝出微服务治理实践笔记,不想竟被GitHub开源阿嘴又又又又又来给大家分享好书了李鑫老师的微服务治理体系架构及实践,网上没找见开源版本!小编会在文末附电子版免费下载方式。李鑫是谁?具有多年大规模复杂系统架构经验,在大规模分布式应李少莉副局长永远走在时尚的前沿,非常钟爱梵克雅宝,为之沉沦美丽和智慧是女人一辈子的追求,尤其是稍微有点姿色的女人,那就更加爱美了,也就更喜欢打扮自己,现任呼和浩特市审批局副局长,李少莉在一场新闻发布会上,妆容精致衣着华贵,随后被眼尖的网友电讯报为得到更多恢复时间,孙兴慜的手术提前至本周五进行直播吧11月4日讯据每日电讯报报道,为得到更多恢复时间来赶上世界杯首战,孙兴慜的手术提前至本周五。报道称,孙兴慜的手术原定于本周末进行,但是手术时间现在已经更改,球员将提前至本周五女性什么时候怀孕最好?经常看到不少人在问女性在什么时候怀孕最好?确实,怀孕太早对自己不好,太晚了对孩子不好,各有各的说法。那到底什么时候是最好的怀孕年龄呢?我国婚姻法规定女性20周岁结婚,这一点无论是从讽刺!李少莉是现代女性的楷模,工作上勤勤恳恳,家庭上勤俭持家在古代,三从四德就是在中国古代封建社会中,女子必须遵守的行为准则与道德规范,也是体现一个女子的高尚品格!最近,内蒙古呼和浩特李少莉副局长火遍全网,遭到了网友们的深扒质疑。她那漂亮的澳大利亚野兔泛滥,政府斗争150年完败,没人吃?本地人吃不了关于澳大利亚的野兔成灾的新闻,可没少让网友们着急。澳大利亚的野兔在这片土地上仿佛霸主一般,根本没有生物能与之抗衡,先后一共上演多次人兔大战,可每次澳大利亚政府都败下阵来。这让人不免要是李少莉的调查结果是清白的,请向李少莉道歉这几天呼和浩特市政务审批的副局长李少莉,因为在发布会上戴了一对梵克雅宝的耳钉,成了争议的焦点,现在李少莉被撤换下来进行调查。翻看网上对于这事的看法,大致有两个态度。一个是觉得李少莉德州淘宝镇增至6个,淘宝村增至9个日前,阿里研究院联合南京大学空间规划研究中心正式发布2022年淘宝镇淘宝村名单,宁津县长官镇时集镇为新增淘宝镇,全市淘宝镇总数达到6个宁津县宁城街道刘振雷村委会大柳镇后魏村委会及庆谁说黑丝显低俗?看完这些明星穿,初秋都不想穿长裤了时尚圈一度十分流行光腿穿搭,尤其是反季节光腿搭配备受小女生们喜爱,但伴随的后遗症也有,譬如冻腿。想好看又想保暖,其实最有效办法就是穿袜子,可不少人觉得厚裤袜显腿粗,薄丝袜显得廉价,vivoX90系列爆料,超大杯配置拉满,网友可以冲击DXOMARK第2名如果说今年上半年哪家的高端旗舰系列最香,个人会毫不犹豫地选择vivoX80系列,该系列一共有3款产品,分别是vivoX80,vivoX80Pro天玑版和vivoX80Pro高通版,不小心发现男友写的恋爱日记正经人谁写日记啊(恼)人被逼急了什么都能做出来,除了数学题累的话就休息一下吧医生互联网真是太精彩了三个TD看得出很急了网友评论夺笋呐哈哈哈明明这是很正常的发言,为什么看起来像稀世珍
人民币市场汇价(11月2日)新华社北京11月2日电中国外汇交易中心11月2日受权公布人民币对美元欧元日元港元英镑澳元新西兰元新加坡元瑞士法郎加元林吉特卢布兰特韩元迪拉姆里亚尔福林兹罗提丹麦克朗瑞典克朗挪威克朗Digitimes苹果XR头显由和硕独家代工,预计2023年Q1量产近日,据中国台媒Digitimes报道称,苹果要求机构厂用半导体无尘室规格组装生产。有供应链人士透露,苹果代号为N301的XR头显最后确定由和硕独家代工,并计划于2023年Q1季度双十一跳水手机大集合,看看哪些机型首发买了成怨种十一月到了,相信有很多消费者最期待的日子,恐怕就是双十一购物节了,因为每当这个时候,就有不少的商品会进行打折促销,用户们喜欢的手机产品更是如此,当然手机厂商们也自然不会错过这次机会iPhone13系列全中招更新iOS16。1或导致花屏据推特网友报告称,iPhone13系列手机在更新到iOS16。1系统后,导致了屏幕花屏。苹果售后方面表示此问题无法通过软件层面解决,只能进行换屏。如果你的手机还在保修期内的话,可以双十一这4款,国产旗舰最适合捡漏,优惠超高还买什么苹果现如今国产手机已经做得非常不错了,发布的旗舰机型基本上都能轻松使用三年以上,流畅使用多年再也不是苹果的专利了,而且价格还要更优惠很多。目前双十一还有领券福利和其他优惠活动,大多数旗i1PublishPro3屏幕校色仪的优点及色彩管理i1PublishPro3屏幕校色仪,快速轻松地为相机显示器数字投影仪扫描仪以及打印机创建自定义的色彩配置文件,确保从采集到输出屏幕颜色校准的色彩准确度。凭借行业的技术,i1ProToryBurch和Siyu品牌泳装系列时尚广告大片EditaVilkeviciute为ToryBurch泳装大片登陆海滩EditaVilkeviciute在海滩上寻找美国设计师ToryBurch的最新广告。这位金发女郎出现在201iPhoneSE4有望采用更大屏幕?5。76。1英寸屏幕11月1日消息,据国外媒体报道,在3月9日凌晨的春季新品发布会上推出搭载A15仿生芯片支持5G的第三代iPhoneSE之后,外界普遍预计苹果未来仍会对这一起售价最低的iPhone进网络爬虫无处不在,侵权边界在哪?刚和朋友聊天提起某款商品,打开购物App后,首页随即出现同类产品的推送广告家人商量打算去某地旅游后,某旅游App马上奉上该地最佳旅游攻略如今,很多人都有类似这样的经历,这种聊啥来啥真相曝光!张继科第一次说起退出国家队的原因!和刘国梁有关11月3日,中国乒乓球国家队最尴尬的选手有3人1)刘诗雯刘诗雯手握20个世界冠军,现役女单选手最多,陪着孙颖莎从成都到澳门,再到新乡!然而这一次2022年全国锦标赛,没有刘诗雯的身留给山东泰山队犯错的机会不多了山东泰山要想卫冕成功,在剩余的12场比赛里一定不要掉以轻心,也不要轻敌,因为留给山东队犯错的机会不多了。在结束的22场比赛中,山东泰山队负3场,平2场,其中负河南和申花队是轻敌所致
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网