如何优雅地停下线程?除了这两种,你还能说出一种算我输
7月23日 夜如影投稿 前言
今天主要来聊一聊如何优雅地停下线程。
在开始之前,我们可以思考一下,如何能够让线程停下?
通过查阅JDK,我们不难发现Thread为我们提供了一个stop方法,只要使用stop方法,就立即停止线程,但是发现stop()方法被标注为废弃的方法,因为这个方法会强行把执行到一半的线程终止,可能会引发一些数据不一致或者我们没发预估的问题。
除了stop()方法,我能想到的方案还有两个,
方案一:使用volatile标记位,利用其可见性
方案二:调用Thread的方法interrupted方案实现方案一:使用volatile标记位,利用其可见性
通过代码我们来看下方案一,这是一个很经典的生产者和消费者模式。
生产者Demo生产者classProducerimplementsRunnable{privatePProducer(Productproduct){this。}Overridepublicvoidrun(){try{while(!canc){try{Thread。sleep(1000);product。put(iphone6s);System。out。println(put:Thread。currentThread()。getName());}catch(InterruptedExceptione){e。printStackTrace();}}}catch(Exceptionex){。。。}finally{System。out。println(结束);}}}
消费者Demo消费者classConsumerimplementsRunnable{privatePConsumer(Productproduct){this。}Overridepublicvoidrun(){while(Math。random()0。9){try{Thread。sleep(1000);product。take(iPhone6s);System。out。println(take:Thread。currentThread()。getName());}catch(InterruptedExceptione){e。printStackTrace();}}}}
调用生产者和消费者publicstaticvoidmain(String〔〕args){ArrayBlockingQueuequeuenewArrayBlockingQueue(1);ProductproductnewProduct(queue);ProducerproducernewProducer(product);ConsumerconsumernewConsumer(product);Threadc1newThread(consumer);Threadp1newThread(producer);p1。start();try{Thread。sleep(500);}catch(InterruptedExceptione){e。printStackTrace();}c1。start();System。out。println(消费者不需要更多数据了。);producer。System。out。println(producer。canc);System。out。println(p1。getState());}
场景一:我们把消费者和生产者的线程都开起来,生产者生产一个产品,消费者都会消费一个产品,这个时候volatile的值,在下一次的轮询中值已经变成了true,就跳出while循环,线程就停止,这个场景下volatile就适用了。
场景二:我们将消费者线程不启动,只生产不消费。理论上我们期待的结果应该也是值变成true,跳出while循环,线程停止。
结果打印:Putaiphone6sput:Thread2消费者不需要更多数据了。valatile的值:true线程状态:WAITING
根据打印的结果我们会观察到他没有输出结束的语句,
我们看到了生产者生产了产品,valatile也修改了值,但是线程却没有结束,
这主要的原因是因为,生产者执行了product。put(iphone6s),没有被消费,造成了阻塞,在它唤醒之前,
无法进入下一次的轮询判断。造成了值修改了,却没有做出相应处理。
我们发现在消费的时候,take方法内部会触发唤醒,当检测到线程已经停止,则抛出InterruptedException异常。开源码说话,可以看到dequeue,唤醒了线程。publicEtake()throwsInterruptedException{finalReentrantLocklockthis。lock。lockInterruptibly();try{while(count0)notEmpty。await();returndequeue();}finally{lock。unlock();}}publicfinalvoidacquireInterruptibly(intarg)throwsInterruptedException{if(Thread。interrupted())thrownewInterruptedException();}privateEdequeue(){。。。释放notFull。signal();}二、方案二:调用Thread的方法interruptedstaticclassCreateRunableimplementsRunnable{publicCreateRunable(inti){this。}publicintgetI(){}publicvoidsetI(inti){this。}Overridepublicvoidrun(){synchronized(this){while(!Thread。currentThread()。isInterrupted()){System。out。println(Runable接口,实现线程i);}}}}ThreadcreateThreadnewThread(newCreateRunable(0));createThread。start();Thread。sleep(5);createThread。interrupt();
休眠5毫秒后,该线程检查到了中断信号,就会停止线程。
那如果任务正在休眠状态,线程会如何处理呢Overridepublicvoidrun(){synchronized(this){while(!Thread。currentThread()。isInterrupted()){try{Thread。sleep(10000);}catch(InterruptedExceptione){e。printStackTrace();}System。out。println(Runable接口,实现线程i);}}}
抛出异常,同时清除中断状态,线程会继续执行Runable接口,实现线程0java。lang。InterruptedException:sleepinterruptedatjava。lang。Thread。sleep(NativeMethod)atmain。Thread。threadStartThreeWaysCreateRunable。run(threadStartThreeWays。java:48)atjava。lang。Thread。run(Thread。java:748)Runable接口,实现线程1Runable接口,实现线程2Runable接口,实现线程3总结
我们在这里就不说Stop()方法,因为他太暴力了,不够优雅。这里的优雅指的是可以让线程有时间做好收尾工作,避免数据的错乱。优雅停下线程的方式主要有两种方案一:使用volatile标记位。方案二:调用Thread的方法interrupted。
通过上面的demo案例,我们可以看到使用方案一的volatile,在某一些特殊的场景下,会发生不能关闭线程的情况。
所以volatile是不够全面的。方案二则是一种更优的选择。
投诉 评论
六位知名艺人集体翻车!代言理财产品跑路,目前涉案金额4000这个世界上总有那么一批人想通过高收益赚取别人的利息,殊不知这会伴随巨大的风险,而别人看上的则是你的本金,一个不小心就会导致血本无归。近日,一个名为同义汇的理财产品爆雷,涉……
跟着大赛游雅安!雅安的美,等你去发现12月13日,骑遍四川2022环茶马古道雅安国际公路自行车赛在雅安启动。来自全国各地的自行车选手将在天府之肺熊猫故乡的魅力赛道中,挑战自我、争夺桂冠。在这里雅雅也诚……
荣耀手机变化太大,从性能走向影音,再从影音走向性能看文章听音乐是种享受,想听什么留言告知(都是付费无损包)比起其他国产品牌如同疯癫的同质化和跟风趋势,如果站在一个理性的方向来重新看荣耀手机,你就会感受到荣耀手机这个品牌和……
春山如笑,迎接美好的女孩名诗词自古就离不开风花雪月,也是这样写景抒情的诗句最令读者着迷,情景交融的画卷徐徐展开,映入眼帘的是一片片诗情画意的田园之色,是一幅幅生机盎然,莺莺燕燕的自然之景,是一脉脉溪水潺……
不比不知道,原来苹果这么过分,相比之下,小米良心多了没想到手机有一天会成为人们生活如此重要的工具,而手机作为电子产品难免会遇到各种售后问题,而对于电子产品的售后问题,国家也有明确的规定。有些品牌出了问题会积面对,而有些大牌却把消……
儿童扁平足的康复干预策略了解正常足弓:足弓的形成:新生儿没有足弓,随着生长发育一般1214岁左右才完全形成。发育过程中,前足后足间的螺旋扭转:婴儿开始直立行走后,足跟逐渐扭向外侧,从足中部……
不装了?华为寒气蔓延,苹果台积电特斯拉等巨头无一幸免在过去3年里,华为遭到了多次打压,这也使得华为陷入了低谷。但好不容易活下来,进入2022年后,全球芯片市场、智能手机市场、电动汽车市场等又进入了寒冬期,华为感受到了浓浓的寒气。……
霸屏热搜!火爆全网的羊了个羊被指抄袭,背后公司回应近日,一款名为羊了个羊小游戏突然爆火,连续霸榜热搜。据悉,这是一款卡通背景的消除闯关游戏。玩家们需要点击上方卡牌,被选中的卡牌会下移到底部的木框中,框内最多可以储存7张卡……
一奶同胞一生一世情一辈子亲情不变夏去秋至,万物开始凋零,微风拨动着花瓣上羞涩可人的露珠,梧桐叶纷纷下落,金黄的稻穗在秋风中摇曳,深红的果实在枝头吵闹,看似冷酷的秋季却带来人们喜悦。国庆节之前我们姐弟就约……
今年低腰裙突然火了!比你想象中时髦高级,小个子女生很适合一直以来在时尚圈内,其实高腰的设计裙装总是会更加受欢迎且成为优选的搭配,而在今年当中真的是想不到低腰裙的搭配突然就火了!其在对于时髦感和洋气感的衬托效果真的是吊打高腰裙,……
美国巨头出尔反尔,退出中国市场又重返,并公然挑战国人底线原创Run琳威互联网时代对人们的生活方式有巨大的影响,它改变了各行各业的运作方式,也催生出一堆从未有过的行业。在互联网行业中,最先创立起来的网购平台就是亚马逊,在国际上也……
对未来的思考我是91年生的人,今年准确讲是31岁了,但从我的身份证年龄讲我已经被迫35岁了,因为小时候身份证父母虚报了4岁,在法律上我不得不承认我是87年生人。之所以说到这事坦白说年龄被迫……