本篇內(nèi)容主要講解“java為什么不要用stop方法停止線程”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“java為什么不要用stop方法停止線程”吧!
創(chuàng)新互聯(lián)專注于永興企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),商城建設(shè)。永興網(wǎng)站建設(shè)公司,為永興等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站策劃,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
線程啟動完畢后,在運(yùn)行時(shí)可能需要終止,Java提供的終止方法只有一個(gè)stop,但是我不建議使用這個(gè)方法,因?yàn)樗幸韵氯齻€(gè)問題:(1)stop方法是過時(shí)的從Java編碼規(guī)則來說,已經(jīng)過時(shí)的方法不建議采用。(2)stop方法會導(dǎo)致代碼邏輯不完整stop方法是一種“惡意”的中斷,一旦執(zhí)行stop方法,即終止當(dāng)前正在運(yùn)行的線程,不管線程邏輯是否完整,這是非常危險(xiǎn)的??慈缦碌拇a:
這段代碼的邏輯是這樣的:子線程是一個(gè)匿名內(nèi)部類,它的run方法在執(zhí)行時(shí)會休眠1秒鐘,然后再執(zhí)行后續(xù)的邏輯,而主線程則是休眠0.1秒后終止子線程的運(yùn)行,也就是說,JVM在執(zhí)行thread.stop()時(shí),子線程還在執(zhí)行sleep(1000),此時(shí)stop方法會清除棧內(nèi)信息,結(jié)束該線程,這也就導(dǎo)致了run方法的邏輯不完整,輸出語句println代表的是一段邏輯,可能非常重要,比如子線程的主邏輯、資源回收、情景初始化等,但是因?yàn)閟top線程了,這些就都不再執(zhí)行,于是就產(chǎn)生了業(yè)務(wù)邏輯不完整的情況。這是極度危險(xiǎn)的,因?yàn)槲覀儾恢雷泳€程會在什么時(shí)候被終止,stop連基本的邏輯完整性都無法保證。而且此種操作也是非常隱蔽的,子線程執(zhí)行到何處會被關(guān)閉很難定位,這為以后的維護(hù)帶來了很多麻煩。(3)stop方法會破壞原子邏輯多線程為了解決共享資源搶占的問題,使用了鎖概念,避免資源不同步,但是正因此原因,stop方法卻會帶來更大的麻煩:它會丟棄所有的鎖,導(dǎo)致原子邏輯受損。例如有這樣一段程序:
MultiThread實(shí)現(xiàn)了Runnable接口,具備多線程能力,其中run方法中加上了synchronized代碼塊,表示內(nèi)部是原子邏輯,它會先自增然后再自減少,按照synchronized同步代碼塊的規(guī)則來處理,此時(shí)無論啟動多少個(gè)線程,打印出來的結(jié)果都應(yīng)該是a=0,但是如果有一個(gè)正在執(zhí)行的線程被stop,就會破壞這種原子邏輯,代碼如下:
首先要說明的是所有線程共享了一個(gè)MultiThread的實(shí)例變量t,其次由于在run方法中加入了同步代碼塊,所以只能有一個(gè)線程進(jìn)入到synchronized塊中。此段代碼的執(zhí)行順序如下:1)線程t1啟動,并執(zhí)行run方法,由于沒有其他線程持同步代碼塊的鎖,所以t1線程執(zhí)行自加后執(zhí)行到sleep方法即開始休眠,此時(shí)a=1。2)JVM又啟動了5個(gè)線程,也同時(shí)運(yùn)行run方法,由于synchronized關(guān)鍵字的阻塞作用,這5個(gè)線程不能執(zhí)行自增和自減操作,等待t1線程鎖釋放。3)主線程執(zhí)行了t1.stop方法,終止了t1線程,注意,由于a變量是所有線程共享的,所以其他5個(gè)線程獲得的a變量也是1。4)其他5個(gè)線程依次獲得CPU執(zhí)行機(jī)會,打印出a值。分析了這么多,相信讀者也明白了輸出的結(jié)果,結(jié)果如下:
原本期望synchronized同步代碼塊中的邏輯都是原子邏輯,不受外界線程的干擾,但是結(jié)果卻出現(xiàn)原子邏輯被破壞的情況,這也是stop方法被廢棄的一個(gè)重要原因:破壞了原子邏輯。既然終止一個(gè)線程不能使用stop方法,那怎樣才能終止一個(gè)正在運(yùn)行的線程呢?答案也很簡單,使用自定義的標(biāo)志位決定線程的執(zhí)行情況,代碼如下:
這是很簡單的辦法,在線程體中判斷是否需要停止運(yùn)行,即可保證線程體的邏輯完整性,而且也不會破壞原子邏輯??赡苡凶x者對Java API比較熟悉,于是提出疑問:Thread不是還提供了interrupt中斷線程的方法嗎?這個(gè)方法可不是過時(shí)方法,那可以使用嗎?它可以終止一個(gè)線程嗎?非常好的問題,interrupt,名字看上去很像是終止一個(gè)線程的方法,但是我可以很明確地告訴你,它不是,它不能終止一個(gè)正在執(zhí)行著的線程,它只是修改中斷標(biāo)志而已,例如下面一段代碼:
執(zhí)行這段代碼,你會發(fā)現(xiàn)一直有Running在輸出,永遠(yuǎn)不會停止,似乎執(zhí)行了interrupt沒有任何變化,那是因?yàn)閕nterrupt方法不能終止一個(gè)線程狀態(tài),它只會改變中斷標(biāo)志位(如果在t1.interrupt()前后輸出t1.isInterrupted()則會發(fā)現(xiàn)分別輸出了false和true),如果需要終止該線程,還需要自行進(jìn)行判斷,例如我們可以使用interrupt編寫出更加簡潔、安全的終止線程代碼
總之,如果期望終止一個(gè)正在運(yùn)行的線程,則不能使用已經(jīng)過時(shí)的stop方法,需要自行編碼實(shí)現(xiàn),如此即可保證原子邏輯不被破壞,代碼邏輯不會出現(xiàn)異常。當(dāng)然,如果我們使用的是線程池(比如ThreadPoolExecutor類),那么可以通過shutdown方法逐步關(guān)閉池中的線程,它采用的是比較溫和、安全的關(guān)閉線程方法,完全不會產(chǎn)生類似stop方法的弊端。
到此,相信大家對“java為什么不要用stop方法停止線程”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!