亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

不關閉JVM的中斷方法

不關閉JVM的中斷方法

幕布斯6054654 2023-02-23 09:52:05
我正在玩以下示例:public static void interrupted() throws InterruptedException {    Runnable task = () -> {        while(true && !Thread.currentThread().isInterrupted()) {            System.out.println("task executing");            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    };        Thread thread = new Thread(task);        thread.start();    //lets allow spawned thread to run by sleeping main thread for 10 seconds     Thread.currentThread().sleep(10000);    thread.interrupt();}當我運行此方法時,我期待:1 通過 Runnable 啟動的任務將運行幾次并打印 SOP上面的 2 是可能的,因為主線程休眠了 10 秒3 一旦主線程喚醒,它就會調用衍生線程的中斷4 在 Runnable 任務中,我們正在檢查 isInterrupted,因此它應該被觸發并且生成的線程應該退出,從而允許 JVM 退出。然而,這并沒有發生,eclipse/jvm 顯示生成的線程仍在運行 while 循環這是控制臺:task executingtask executingjava.lang.InterruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at basics.StopEx.lambda$1(StopEx.java:39)at java.lang.Thread.run(Thread.java:748)task executingtask executingtask executingtask executing........關于中斷的 java 文檔似乎表明調用“睡眠”會導致不同的行為(下面突出顯示)-有人可以闡明這里到底發生了什么以及為什么嗎?中斷此線程。除非當前線程正在中斷自身(這始終是允許的),否則將調用此線程的 checkAccess 方法,這可能會導致拋出 SecurityException。如果此線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法或 join()、join(long)、join(long, int) 方法時被阻塞, sleep(long), or sleep(long, int), 這個類的方法,然后它的中斷狀態將被清除,它會收到一個 InterruptedException。如果此線程在 InterruptibleChannel 上的 I/O 操作中被阻塞,則通道將關閉,線程的中斷狀態將被設置,線程將收到 java.nio.channels.ClosedByInterruptException。如果此線程在 java.nio.channels.Selector 中被阻塞,則線程的中斷狀態將被設置,并且它將立即從選擇操作返回,可能返回一個非零值,就像選擇器的喚醒方法被調用一樣。如果前面的條件都不成立,那么將設置該線程的中斷狀態。中斷一個不活動的線程不需要有任何影響。
查看完整描述

3 回答

?
蕭十郎

TA貢獻1815條經驗 獲得超13個贊


這是因為中斷標志如何為線程工作。


當您中斷一個線程時,基本上只會發生一件事:設置中斷標志,僅此而已。然后取決于該線程正在運行的代碼是否確實執行了操作。


一般的想法是,如果可以的話,你會中止你正在做的事情并拋出一些合理的異常。


java 內置的一些方法保證這正是它們的工作方式。您可以輕松識別它們:它們都被聲明為 throw InterruptedException。有許多方法在中斷時故意未定義行為(這取決于操作系統):所有那些阻塞 I/O 方法都是這樣的。如果您處于阻塞網絡讀取中并且中斷讀取時阻塞的線程,則可能會導致讀取調用時出現 IOException,或者.. 不會。


更重要的是,當“處理”中斷時(中止+拋出異常正在處理它!),標志被清除。


請注意,如果您使用檢查標志的標準方法(即Thread.interrupted(). 這個方法檢查你自己線程的中斷標志并清除它。if使用這個:你已經寫了一個聲明或諸如此類的東西來處理中斷這一事實意味著你已經處理了它。


因此,如果您只想返回以響應被打斷,正確的代碼是:


    Runnable task = () -> {

        while (!Thread.interrupted()) {

            System.out.println("Executing");

            try {

                Thread.sleep(5000);

            } catch (InterruptedException e) {

                return;

            }

        }

    };

無論中斷何時發生,此方法都會退出。在 99.99% 的情況下,它會在阻塞睡眠時發生。然后標志將為假,并拋出異常。在不太可能發生的情況下,它會在其外部處理時發生,而 while 條件將拾取它。


請注意,如果您提高了中斷標志并調用了類似的方法Thread.sleep,該方法將通過清除標志并拋出來立即InterruptedException完成執行。不管中斷發生在哪里,上面的例子都會做同樣的事情(靜默退出run方法,中斷標志將被清除)。


查看完整回答
反對 回復 2023-02-23
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

InterruptedException并且Thread.isInterrupted()實際上非常獨立。sleep()當您在長時間運行的循環中使用時,會引入并發癥。你sleep(5000)實際上是清除你的isInterrupted標志并拋出InterruptedException.


如果您嘗試以下操作,您會發現線程實際上沒有InterruptException拋出。interrupt()


    @Override public void run() {

        int b = 0;

        while (true) {

            if (b++ == 0) System.out.println("running...");

        }

    }

教訓是,您確實需要同時檢查異常和標志,但它們不應該相互依賴。例如,您的示例捕獲異常,但依賴標志退出循環。如您所見,這是行不通的。


您要么需要break在異常被捕獲時退出 while 循環,要么在循環try/catch 之外(確保捕獲異常使您脫離循環)。


因此,應提供以下任一服務:


    while (!Thread.currentThread().isInterrupted()) { // out of the loop when flag is raised 

        try {   

            //......

        } 

        catch (InterruptedException e) { 

            break;//exit loop when exception thrown

        }

    }


    // Or:

    try {   

        while (!Thread.currentThread().isInterrupted()) { // exit loop when flag is raised

            //.....

        }

    } 

    catch (InterruptedException e) { 

        // no need to break, as we're already outside

    }


查看完整回答
反對 回復 2023-02-23
?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

這是帶有打印語句的代碼。


public static void interrupted() throws InterruptedException {

      Runnable task = () ->

      {

         while (true && !Thread.currentThread().isInterrupted()) {

            System.out.println("task executing");

            try {

               Thread.sleep(5000);

            }

            catch (InterruptedException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

// this prints false.

               System.out.println(Thread.currentThread().isInterrupted());

            }

         }

      };

一旦處理完中斷狀態,線程就不再被認為處于中斷狀態,因此循環繼續。


查看完整回答
反對 回復 2023-02-23
  • 3 回答
  • 0 關注
  • 138 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號