当前位置: 首页 > 后端技术 > Java

为什么强烈不建议使用stop和suspend方法来中断线程?_0

时间:2023-04-01 16:20:20 Java

我们知道stop、suspend等中断或阻塞线程的方法在java高版本中都被打上了@Deprecated过期标签,那么为什么它们一直登上java的历史舞台并逐渐退出舞台,是人性的扭曲还是道德的沦丧,还是被不思进取所取代?如果他们被取代,那么取代他们的人是谁?1.stop结束首先,stop方法的作用是什么?使用java源码中的一段注释来理解:Forcesthethreadtostopexecution.,即强制线程停止执行。‘力量’似乎已经透露出停止法的含义。残忍无理。那么我们来看看java开发者是如何解释stop被消除的:我们可以从中看出以下几点:我们再来看看上面提到的两点:publicstaticvoidmain(String[]args)throwsInterruptedException{Objecto1=新对象();对象o2=新对象();线程T1=新线程(()->{同步(O1){同步(O2){try{system.out.ut.println(“t1toto”);thread.sleep(5000);system.out.out.println(“”(T1结束");}Catch(interruptedExceptionE){e.printstacktrace();}}});T1.start();线程.睡眠(1000);ThreadT2=NewThread(()->{synchronized(O1){synchronized(O2){try{System.out.println("T2getlock");thread.s利普(5000);System.out.println("T2结束");}Catch(interruptedExceptionE){e.printstacktrace();}}});t2.开始();结果:可以看出,当线程t1获取到o1和o2的两把锁开始执行时,在执行结束前,主线程调用了t1的stop方法中断了t1的执行,并释放了获取到的锁t1线程所有的锁,中断后t2获取了o1和o2的锁,开始执行直到结束,但是t1死在了sleep中,sleep之后的代码没有执行。所以,使用stop,我们不知道线程跑到哪里去了,很暴力。如果线程被打断,如果sleep之后的代码是资源释放、重要业务逻辑等比较重要的代码,或者其他线程依赖t1线程的运行结果,那么直接打断可能会造成严重的后果。所以不推荐使用stop来中断线程。我们应该如何优雅地结束一个线程?我们可以在java开发者的评论中找到解决方法:可以看到java开发者推荐我们使用以下两种方式优雅的停止线程:1.定义一个变量,目标线程会不断的检查这个变量的状态,并在变量达到某个状态时停止线程。代码举示例如下:volatilestaticbooleanflag=false;publicstaticvoidmain(String[]args)throwsInterruptedException{Objecto1=newObject();Threadt1=newThread(()->{同步(o1){try{System.out.println("T1getslocks");while(!Flag)thread.sleep(5000);//执行业务逻辑系统。out.println("T1结束");}Catch(interuptedExceptionE){{e.printstacktrace();}});t1.start();线程睡眠(1000);ThreadT2=NewThread(()->{Synchronized(O1){Try{System.out.println("T2t2获取锁");thread.sleep(5000);//执行业务逻辑system.out.println("T2结束");}Catch(interruptedExceptionE){e.printstacktrace();}}}});t2.开始();标志=真;}运行结果:2.使用interrupt方法中断线程代码举示例如下:publicstaticvoidmain(String[]args)throwsInterruptedException{Objecto1=newObject();Threadt1=newThread(()->{同步(o1){System.out.println("t1获取锁");while(!Thread.currentthRead().Isinterrupted()){for(inti=0;i<100;i++){if(i==50)system.out.println();System.out.print(i+"");}System.out.println();}System.out.println("T1结束");}});t1.start();threadt2=newthread(()->{Synchronized(O1){try{system.out.println("T2获取锁");thread.sleep(5000);//执行业务逻辑system.out.println("T2结束");}Catch(InterruptedExceptione){如果被中断,线程自然死亡,释放锁。可以看到调用interrupt方法后,不会像stop那样暴力中断线程。它会等到当前运行的逻辑结束后,再检查是否被中断,非常优雅。二、结束suspendsuspend方法的作用是挂起一个线程,直到调用resume方法恢复线程,但是调用suspend方法后,被挂起的线程获得的锁并不会释放,所以suspend和两兄弟的简历都被打上了容易造成死锁的标签。当然,这也是导致停复牌退出历史舞台的罪魁祸首。同样的,我们看看java开发者给出的取消suspend的理由:从中我们可以得出以下结论:接下来模拟一下suspend造成的死锁场景,话不多说,秀一下我的代码:publicstaticvoidmain(String[]ARGS)抛出InterruptedException{ObjectO1=NewObject();对象O2=新对象();ThreadT1=NewThread(()->{SynchronEd(O1){System.urn.锁开始执行"));Try{thread.sleep(5000);//模拟业务逻辑}Catch(InterruptedExceptionE){e.printstacktrace();}System.out.println("T1执行结束");}}}});Start();ThreadT2=NewThread(()->{Synchronized(O2){system.out.println("T2获取O2开始执行");try{thread.sleep(2000);//执行耗时业务}catch(InterruptedExceptione){e.printStackTrace();}synchronized(O1){system.out.println("T2获得O1锁并开始执行");}System.out.println("T2执行结束");t2.开始();线程.睡眠(1000);t1.暂停();//假设抛出未知异常inti=1/0;t1.resume();Resume在恢复t1线程前抛出未知异常,导致t1挂起无法释放o1锁,而t2需要先获取o1锁才能继续执行,但苦苦等待,但o1被t1紧紧控制,从此整个程序陷入无尽的等待----死锁作者:郎舟子blog.csdn.net/qq_40400960/article/details/112651249