色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何用interrupt停止線程

Android編程精選 ? 來源:CSDN ? 作者:CSDN ? 2022-05-04 17:18 ? 次閱讀
啟動線程需要調用 Thread 類的 start() 方法,并在 run() 方法中定義需要執行的任務。啟動一個線程非常簡單,但如果想要正確停止它就沒那么容易了。

為什么不強制停止

對于 Java 而言,最正確的停止線程的方式是使用 interrupt。但 interrupt僅僅起到通知被停止線程的作用。而對于被停止的線程而言,它擁有完全的自主權,它既可以選擇立即停止,也可以選擇一段時間后停止,也可以選擇壓根不停止。

為什么 Java 不提供強制停止線程的能力呢?

事實上,Java 希望程序間能夠相互通知、相互協作地管理線程,因為如果不了解對方正在做的工作,貿然強制停止線程就可能會造成一些安全的問題。

比如:

線程正在寫入一個文件,這時收到終止信號,它就需要根據自身業務判斷,是選擇立即停止,還是將整個文件寫入成功后停止。如果選擇立即停止就可能造成數據不完整,不管是中斷命令發起者,還是接收者都不希望數據出現問題。

如何用 interrupt 停止線程

while(!Thread.currentThread().isInterrupted()
&&moreworktodo){
domorework
}

我們一旦調用某個線程的 interrupt() 之后,這個線程的中斷標記位就會被設置成 true。每個線程都有這樣的標記位,當線程執行時,應該定期檢查這個標記位,如果標記位被設置成 true,就說明有程序想終止該線程。

回到源碼,可以看到在 while 循環體判斷語句中,首先通過 Thread.currentThread().isInterrupt() 判斷線程是否被中斷,隨后檢查是否還有工作要做。&& 邏輯表示只有當兩個判斷條件同時滿足的情況下,才會去執行下面的工作。

來段代碼瞅瞅。

publicclassStopThreadimplementsRunnable{

@Override
publicvoidrun(){
intcount=0;
while(!Thread.currentThread().isInterrupted()&&count1000){
System.out.println("count="+count++);
}
}

publicstaticvoidmain(String[]args)throwsInterruptedException{
Threadthread=newThread(newStopThread());
thread.start();
Thread.sleep(5);
thread.interrupt();
}
}

在 StopThread 類的 run() 方法中,首先判斷線程是否被中斷,然后判斷 count 值是否小于 1000。

這個線程的工作內容很簡單,就是打印 0~999 的數字,每打印一個數字 count 值加 1,可以看到,線程會在每次循環開始之前,檢查是否被中斷了。接下來在 main 函數中會啟動該線程,然后休眠 5 毫秒后立刻中斷線程,該線程會檢測到中斷信號,于是在還沒打印完1000個數的時候就會停下來,這種就屬于通過 interrupt 正確停止線程的情況。

sleep 期間能否感受到中斷

先說結論,可以。

publicclassStopDuringSleep{

publicstaticvoidmain(String[]args)throwsInterruptedException{
Runnablerunnable=()->{
intnum=0;
try{
while(!Thread.currentThread().isInterrupted()&&num<=?1000){
System.out.println(num);
num++;
Thread.sleep(1000000);
}
}catch(InterruptedExceptione){
e.printStackTrace();
}
};
Threadthread=newThread(runnable);
thread.start();
Thread.sleep(5);
thread.interrupt();
}
}

運行后的結果你猜這么著,程序會拋出異常

ec708e1c-c3c3-11ec-bce3-dac502259ad0.png

如果 sleep、wait 等可以讓線程進入阻塞的方法使線程休眠了,而處于休眠中的線程被中斷,那么線程是可以感受到中斷信號的,并且會拋出一個 InterruptedException 異常,同時清除中斷信號,將中斷標記位設置成 false。這樣一來就不用擔心長時間休眠中線程感受不到中斷了,因為即便線程還在休眠,仍然能夠響應中斷通知,并拋出異常。

但是這樣只能相應一次中斷信號了,怎么辦?

合理利用好 try/catch

我們在實際開發中不能盲目吞掉中斷,如果不在方法簽名中聲明,也不在 catch 語句塊中再次恢復中斷,而是在 catch 中不作處理,我們稱這種行為是“屏蔽了中斷請求”。如果我們盲目地屏蔽了中斷請求,會導致中斷信號被完全忽略,最終導致線程無法正確停止。

try{
Thread.sleep(2000);
}catch(InterruptedExceptione){
//此處處理中斷異常請求
}

停止線程的方式有幾種

  • void shutdown;
  • boolean isShutdown;
  • boolean isTerminated;
  • boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
  • List shutdownNow;

下面我們就對這些方法逐一展開。

shutdown()

調用 shutdown() 方法之后線程池并不是立刻就被關閉,因為這時線程池中可能還有很多任務正在被執行,或是任務隊列中有大量正在等待被執行的任務,調用 shutdown() 方法后線程池會在執行完正在執行的任務和隊列中等待的任務后才徹底關閉。

但這并不代表 shutdown() 操作是沒有任何效果的,調用 shutdown() 方法后如果還有新的任務被提交,線程池則會根據拒絕策略直接拒絕后續新提交的任務。

isShutdown()

它可以返回 true 或者 false 來判斷線程池是否已經開始了關閉工作,也就是是否執行了 shutdown 或者 shutdownNow 方法。這里需要注意,如果調用 isShutdown() 方法的返回的結果為 true 并不代表線程池此時已經徹底關閉了,這僅僅代表線程池開始了關閉的流程,也就是說,此時可能線程池中依然有線程在執行任務,隊列里也可能有等待被執行的任務。

isTerminated()

這個方法可以檢測線程池是否真正“終結”了,這不僅代表線程池已關閉,同時代表線程池中的所有任務都已經都執行完畢了,因為我們剛才說過,調用 shutdown 方法之后,線程池會繼續執行里面未完成的任務,不僅包括線程正在執行的任務,還包括正在任務隊列中等待的任務。

比如此時已經調用了 shutdown 方法,但是有一個線程依然在執行任務,那么此時調用 isShutdown 方法返回的是 true ,而調用 isTerminated 方法返回的便是 false ,因為線程池中還有任務正在在被執行,線程池并沒有真正“終結”。直到所有任務都執行完畢了,調用 isTerminated() 方法才會返回 true,這表示線程池已關閉并且線程池內部是空的,所有剩余的任務都執行完畢了。

awaitTermination()

第四個方法叫作 awaitTermination(),它本身并不是用來關閉線程池的,而是主要用來判斷線程池狀態的。比如我們給 awaitTermination 方法傳入的參數是 10 秒,那么它就會陷入 10 秒鐘的等待,直到發生以下三種情況之一:

  • 等待期間(包括進入等待狀態之前)線程池已關閉并目所有已提交的任務(包括正在執行的和隊列中等待的都執行完畢,相當于線程池已經“終結”了,方法便會返回true
  • 等待超時時間到后,第一種線程池“終結”的情況始終未發生,方法返回 false
  • 等待期間線程被中斷,方法會拋出 Interruptedexception異常

等待期間(包括進入等待狀態之前)線程池已關閉并且所有已提交的任務(包括正在執行的和隊列中等待的)都執行完畢,相當于線程池已經“終結”了,方法便會返回 true;

等待超時時間到后,第一種線程池“終結”的情況始終未發生,方法返回 false;等待期間線程被中斷,方法會拋出 InterruptedException 異常。

shutdownNow()

最后一個方法是 shutdownNow(),也是 5 種方法里功能最強大的,它與第一種 shutdown 方法不同之處在于名字中多了一個單詞 Now,也就是表示立刻關閉的意思。參考這里:shutdown 和 shutdownNow 的區別

在執行 shutdownNow 方法之后,首先會給所有線程池中的線程發送 interrupt 中斷信號,嘗試中斷這些任務的執行,然后會將任務隊列中正在等待的所有任務轉移到一個 List 中并返回,我們可以根據返回的任務 List 來進行一些補救的操作,例如記錄在案并在后期重試。

publicListshutdownNow(){
Listtasks;
finalReentrantLockmainLock=this.mainLock;
mainLock.lock();

try{
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks=drainQueue();
}finally{
mainLock.unlock();
}

tryTerminate();
returntasks;
}

源碼中有一行 interruptWorkers() 代碼,這行代碼會讓每一個已經啟動的線程都中斷,這樣線程就可以在執行任務期間檢測到中斷信號并進行相應的處理,提前結束任務。

這里需要注意的是,由于 Java 中不推薦強行停止線程的機制的限制,即便我們調用了 shutdownNow 方法,如果被中斷的線程對于中斷信號不理不睬,那么依然有可能導致任務不會停止。

總結

中斷和關閉線程的方式五花八門,看起來很相似,其實里頭大有門道。處理不好,可是會導致程序崩潰的。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2972

    瀏覽量

    104867
  • 線程
    +關注

    關注

    0

    文章

    505

    瀏覽量

    19708

原文標題:如何正確的停掉線程?這里面大有門道!

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    socket 多線程編程實現方法

    在現代網絡編程中,多線程技術被廣泛應用于提高服務器的并發處理能力。Socket編程是網絡通信的基礎,而將多線程技術應用于Socket編程,可以顯著提升服務器的性能。 多線程編程的基本概念 多
    的頭像 發表于 11-12 14:16 ?402次閱讀

    CPU線程和程序線程的區別

    CPU的線程與程序的線程在概念、作用、實現方式以及性能影響等方面存在顯著差異。以下是對兩者區別的詳細闡述,旨在深入探討這一技術話題。
    的頭像 發表于 09-02 11:18 ?1084次閱讀

    鴻蒙開發:線程模型

    FA模型下的線程主要有如下三類
    的頭像 發表于 06-24 17:27 ?442次閱讀
    鴻蒙開發:<b class='flag-5'>線程</b>模型

    探索虛擬線程:原理與實現

    虛擬線程的引入與優勢 在Loom項目之前,Java虛擬機(JVM)中的線程是通過java.lang.Thread類型來實現的,這些線程被稱為平臺線程。 然而,平臺
    的頭像 發表于 06-24 11:35 ?321次閱讀
    探索虛擬<b class='flag-5'>線程</b>:原理與實現

    鴻蒙開發:【線程模型】

    管理其他線程的ArkTS引擎實例,例如使用TaskPool(任務池)創建任務或取消任務、啟動和終止Worker線程
    的頭像 發表于 06-13 16:38 ?428次閱讀
    鴻蒙開發:【<b class='flag-5'>線程</b>模型】

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序中包含了兩個或以上的線程,每個線程都可以并行執行不同的任務或操作。Java中的多線程可以提高程序
    的頭像 發表于 03-14 16:55 ?755次閱讀

    python中5種線程鎖盤點

    線程安全是多線程或多進程編程中的一個概念,在擁有共享數據的多條線程并行執行的程序中,線程安全的代碼會通過同步機制保證各個線程都可以正常且正確
    發表于 03-07 11:08 ?1623次閱讀
    python中5種<b class='flag-5'>線程</b>鎖盤點

    FX3/CX3(CYUSB3065) 線程停止是什么原因,有辦法解決嗎?

    我使用FX3/CX3(CYUSB3065) 通過DMA的方式來攝像,然后用一組 I2C來控制攝像的配置, 同時這組I2C還控制另一顆芯片,這顆芯片需要不定時的訪問, 然后線程就不再被調起了(攝像也
    發表于 02-29 08:19

    什么是動態線程池?動態線程池的簡單實現思路

    因此,動態可監控線程池一種針對以上痛點開發的線程池管理工具。主要可實現功能有:提供對 Spring 應用內線程池實例的全局管控、應用運行時動態變更線程池參數以及
    的頭像 發表于 02-28 10:42 ?659次閱讀

    RTT Nano線程創建成功,沒有進入線程創建的函數運行怎么解決?

    RTT Nano線程創建成功,沒有進入線程創建的函數運行int main(void) { interrupt_config(); // gd_eval_led_init(LED1
    發表于 02-26 06:27

    linux多線程編程實例

    linux線程
    的頭像 發表于 02-15 21:16 ?491次閱讀
    linux多<b class='flag-5'>線程</b>編程實例

    arduino如何停止loop循環

    Arduino的loop循環是其主要的程序執行部分,該循環將在Arduino開發板上持續運行,并且只有在程序被重新上傳或開發板斷電重啟時才會停止。然而,在某些情況下,你可能需要在程序執行過程中停止
    的頭像 發表于 02-14 16:24 ?4602次閱讀

    線程是什么的基本單位 進程與線程的本質區別

    線程是操作系統中處理器調度的基本單位,它代表著獨立的執行流。在一個進程中,可以包含多個線程,這些線程共享相同的進程資源,如內存空間、文件描述符等。 進程是操作系統中運行的程序的實例,它包含了程序
    的頭像 發表于 02-02 16:30 ?965次閱讀

    .NET8性能優化之線程

    目前來說,沒有確切的證據證明哪個線程池好用,或者效率更高。但是開發者可以使用上面的選項來進行自己的選擇,有一個測試就是在Windows線程池在比較大的機器上的IO擴展性不太好。如果你的應用程序已經
    的頭像 發表于 01-22 14:50 ?1181次閱讀

    Redis7單線程與多線程詳解

    主要是指Redis的網絡IO和鍵值對讀寫是由一個線程來完成的。
    的頭像 發表于 01-16 17:33 ?1874次閱讀
    Redis7單<b class='flag-5'>線程</b>與多<b class='flag-5'>線程</b>詳解
    主站蜘蛛池模板: 亚洲AV无码一区二区三区乱子伦 | 宫交拔不出来了h黑人| 粉嫩自拍 偷拍 亚洲| 国产在线一区二区AV视频| 精品久久久99大香线蕉| 捏揉舔水插按摩师| 帅哥操帅哥| 伊人久久大香线蕉avapp下载| japanesen女同| 黑人开嫩苞| 欧美深深色噜噜狠狠yyy| 亚洲精品高清在线观看| xxxxx69hd杨幂| 好好的曰com久久| 日韩午夜影院| 艺术片 快播| 国产免费人成在线视频有码| 久久婷婷国产五月综合色啪最新 | 久久免费视频1| 日韩高清在线亚洲专区| 一区一区三区产品| 国产精品久久久亚洲偷窥女厕| 恋夜影视列表免费安卓手机版| 污文乖不疼的| 边吃胸边膜下床震免费版视频| 久久99亚洲AV无码四区碰碰 | 久久精品国产在热亚洲完整版| 色婷婷国产精品视频一区二区三区| 一边吃奶一边添P好爽故事| 国产精品成人免费视频99| 日韩大胆视频| 调教日本美女| 男人天堂黄色| 98久久人妻无码精品系列蜜桃| 久久性生大片免费观看性| 亚洲欧美人成视频在线| 国产睡熟迷奷系列精品| 无限资源好看片2019免费观看| 港台三级大全| 四虎国产精品永久一区高清| 穿白丝袜边走边尿白丝袜|