如何正確的結(jié)束Java線程?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
成都創(chuàng)新互聯(lián)公司2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站制作、網(wǎng)站設(shè)計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元鄂倫春做網(wǎng)站,已為上家服務(wù),為鄂倫春各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792
使用標(biāo)志位
很簡單地設(shè)置一個標(biāo)志位,名稱就叫做isCancelled。啟動線程后,定期檢查這個標(biāo)志位。如果isCancelled=true,那么線程就馬上結(jié)束。
public class MyThread implements Runnable{ private volatile boolean isCancelled; public void run(){ while(!isCancelled){ //do something } } public void cancel(){ isCancelled=true; } }
注意的是,isCancelled需要為volatile,保證線程讀取時isCancelled是最新數(shù)據(jù)。
我以前經(jīng)常用這種簡單方法,在大多時候也很有效,但并不完善??紤]下,如果線程執(zhí)行的方法被阻塞,那么如何執(zhí)行isCancelled的檢查呢?線程有可能永遠(yuǎn)不會去檢查標(biāo)志位,也就卡住了。
使用中斷
Java提供了中斷機制,Thread類下有三個重要方法。
public void interrupt()
public boolean isInterrupted()
public static boolean interrupted(); // 清除中斷標(biāo)志,并返回原狀態(tài)
每個線程都有個boolean類型的中斷狀態(tài)。當(dāng)使用Thread的interrupt()方法時,線程的中斷狀態(tài)會被設(shè)置為true。
下面的例子啟動了一個線程,循環(huán)執(zhí)行打印一些信息。使用isInterrupted()方法判斷線程是否被中斷,如果是就結(jié)束線程。
public class InterruptedExample { public static void main(String[] args) throws Exception { InterruptedExample interruptedExample = new InterruptedExample(); interruptedExample.start(); } public void start() { MyThread myThread = new MyThread(); myThread.start(); try { Thread.sleep(3000); myThread.cancel(); } catch (InterruptedException e) { e.printStackTrace(); } } private class MyThread extends Thread{ @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { System.out.println("test"); Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("interrupt"); //拋出InterruptedException后中斷標(biāo)志被清除,標(biāo)準(zhǔn)做法是再次調(diào)用interrupt恢復(fù)中斷 Thread.currentThread().interrupt(); } } System.out.println("stop"); } public void cancel(){ interrupt(); } } }
對線程調(diào)用interrupt()方法,不會真正中斷正在運行的線程,只是發(fā)出一個請求,由線程在合適時候結(jié)束自己。
例如Thread.sleep這個阻塞方法,接收到中斷請求,會拋出InterruptedException,讓上層代碼處理。這個時候,你可以什么都不做,但等于吞掉了中斷。因為拋出InterruptedException后,中斷標(biāo)記會被重新設(shè)置為false!看sleep()的注釋,也強調(diào)了這點。
@throws InterruptedException if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown. public static native void sleep(long millis) throws InterruptedException;
記得這個規(guī)則:什么時候都不應(yīng)該吞掉中斷!每個線程都應(yīng)該有合適的方法響應(yīng)中斷!
所以在InterruptedExample例子里,在接收到中斷請求時,標(biāo)準(zhǔn)做法是執(zhí)行Thread.currentThread().interrupt()恢復(fù)中斷,讓線程退出。
從另一方面談起,你不能吞掉中斷,也不能中斷你不熟悉的線程。如果線程沒有響應(yīng)中斷的方法,你無論調(diào)用多少次interrupt()方法,也像泥牛入海。
用Java庫的方法比自己寫的要好
自己手動調(diào)用interrupt()方法來中斷程序,OK。但是Java庫提供了一些類來實現(xiàn)中斷,更好更強大。
Executor框架提供了Java線程池的能力,ExecutorService擴展了Executor,提供了管理線程生命周期的關(guān)鍵能力。其中,ExecutorService.submit返回了Future對象來描述一個線程任務(wù),它有一個cancel()方法。
下面的例子擴展了上面的InterruptedExample,要求線程在限定時間內(nèi)得到結(jié)果,否則觸發(fā)超時停止。
public class InterruptByFuture { public static void main(String[] args) throws Exception { ExecutorService es = Executors.newSingleThreadExecutor(); Future<?> task = es.submit(new MyThread()); try { //限定時間獲取結(jié)果 task.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { //超時觸發(fā)線程中止 System.out.println("thread over time"); } catch (ExecutionException e) { throw e; } finally { boolean mayInterruptIfRunning = true; task.cancel(mayInterruptIfRunning); } } private static class MyThread extends Thread { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { System.out.println("count"); Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("interrupt"); Thread.currentThread().interrupt(); } } System.out.println("thread stop"); } public void cancel() { interrupt(); } } }
Future的get方法可以傳入時間,如果限定時間內(nèi)沒有得到結(jié)果,將會拋出TimeoutException。此時,可以調(diào)用Future的cancel()方法,對任務(wù)所在線程發(fā)出中斷請求。
cancel()有個參數(shù)mayInterruptIfRunning,表示任務(wù)是否能夠接收到中斷。
mayInterruptIfRunning=true時,任務(wù)如果在某個線程中運行,那么這個線程能夠被中斷;
mayInterruptIfRunning=false時,任務(wù)如果還未啟動,就不要運行它,應(yīng)用于不處理中斷的任務(wù)
要注意,mayInterruptIfRunning=true表示線程能接收中斷,但線程是否實現(xiàn)了中斷不得而知。線程要正確響應(yīng)中斷,才能真正被cancel。
線程池的shutdownNow()會嘗試停止池內(nèi)所有在執(zhí)行的線程,原理也是發(fā)出中斷請求。
Java的基本數(shù)據(jù)類型分為:1、整數(shù)類型,用來表示整數(shù)的數(shù)據(jù)類型。2、浮點類型,用來表示小數(shù)的數(shù)據(jù)類型。3、字符類型,字符類型的關(guān)鍵字是“char”。4、布爾類型,是表示邏輯值的基本數(shù)據(jù)類型。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。
新聞名稱:如何正確的結(jié)束Java線程
分享鏈接:http://jinyejixie.com/article6/iisgig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計公司、軟件開發(fā)、外貿(mào)建站、面包屑導(dǎo)航、企業(yè)建站、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)