成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊 Java 中的中斷機制

開發 后端
在Java中,用于終止一個正在運行中的線程,并非調用stop方法,而是自行設置一個標志位,在安全點檢測標志位,決定是否退出,但也可能會因為線程被掛起,無法走到標志位。

[[439899]]

在Java中,用于終止一個正在運行中的線程,并非調用stop方法,而是自行設置一個標志位,在安全點檢測標志位,決定是否退出,但也可能會因為線程被掛起,無法走到標志位。因此,Java線程提供了中斷機制,Thread類提供了中斷線程執行的調用方法:interrupt,用于中斷因線程掛起的等待,調用interrupt方法后,線程會被喚醒,待下次cpu調度就會繼續執行中斷后的代碼 。

我們經常會調用Thread#sleep、Object#wait、Queue#poll等方法,并要求我們處理InterruptedException異常。 那么,拋出InterruptedException后,線程會終止嗎?

如果不捕獲InterruptedException,那么線程就會因為異常終止,是因為異常終止,并不是因為被中斷。如果捕獲了InterruptedException,那么線程就不會終止。

中斷,其實只是jvm用于喚醒因鎖競爭、I/O操作、休眠等待被掛起的線程,并設置一個中斷標志,我們可以利用這個標志去做一些處理。比如,當我們發送消息給遠程服務器,并休眠等待結果時,如果線程被喚醒,并設置了中斷標志,此時我們可以知道,并非等到結果被喚醒的,而是被中斷喚醒的,可以決定是繼續等待結果,還是放棄等待。

xxl-job提供取消任務操作,而任何運行中的線程,都只能利用中斷機制去結束線程任務,所以我們想要任務支持被取消,那么在寫定時任務時,一定要考慮清楚,是不是應該捕獲InterruptedException,如何利用中斷標志結束任務,否則將會導致任務無法被取消。

我們來看個案例:

  1. @Test 
  2. public void test() { 
  3.     ExecutorService executorService = Executors.newSingleThreadExecutor(); 
  4.     Future<?> future = executorService.submit(() -> { 
  5.         while (true) { 
  6.             System.out.println( "rung....." ); 
  7.             ThreadUtils.sleep(1000); 
  8.         } 
  9.     }); 
  10.     ThreadUtils.sleep(1000); 
  11.     future.cancel(true); 
  12.     try { 
  13.         future.get(); 
  14.     } catch (InterruptedException | CancellationException | ExecutionException e) { 
  15.         e.printStackTrace(); 
  16.     } 
  17.     ThreadUtils.sleep(1000 * 60); 

此案例創建了只有一個線程的線程池,提交了一個死循序任務,該任務只調用ThreadUtils.sleep方法進入休眠。平常我們調用Thread.sleep方法都要求是否捕獲中斷異常,很多時候我們都會嫌棄麻煩,就用一個工具類提供sleep方法,然后將中斷異常捕獲,如ThreadUtils:

  1. public class ThreadUtils { 
  2.     public static void sleep(long millis) { 
  3.         try { 
  4.             Thread.sleep(millis); 
  5.         } catch (InterruptedException ignored) { 
  6.         } 
  7.     } 

此案例中,由于我們捕獲了中斷異常,因此這會導致任務并不會被終止,只是當我們調用future的get方法時會拋出CancellationException異常,如下圖所示。

任務依然在運行中......

因此,在實際開發中,如果我們開發的Job也是如此,將會導致Job無法被中斷取消,直至Job執行完成或者重啟。在開發Job時,應當合理考慮是否要捕獲中斷異常。

如果我們希望案例中的任務能夠被終止,我們可以這樣處理:

  1. @Test 
  2. public void test() { 
  3.     ExecutorService executorService = Executors.newSingleThreadExecutor(); 
  4.     Future<?> future = executorService.submit(() -> { 
  5.         while (true) { 
  6.             System.out.println( "rung....." ); 
  7.             try { 
  8.                 Thread.sleep(1000); 
  9.             } catch (InterruptedException ex) { 
  10.                 System.err.println( "interrupted" ); 
  11.                 return; // 退出死循環 
  12.             } 
  13.         } 
  14.     }); 
  15.     ThreadUtils.sleep(1000); 
  16.     future.cancel(true); 
  17.     try { 
  18.         future.get(); 
  19.     } catch (InterruptedException | CancellationException | ExecutionException e) { 
  20.         e.printStackTrace(); 
  21.     } 
  22.     ThreadUtils.sleep(1000 * 60); 

關于Thread的interrupt方法,注釋描述的大致意思如下:

  • 如果被中斷的線程,當前是調用Object#wait、Thread#join、Thread#sleep方法,將收到InterruptedException,并且會清除中斷標志;
  • 如果此線程在I/O操作中(指java nio)被阻塞,調用interrupt方法通道將被關閉,線程將收到一個ClosedByInterruptException,并且會設置中斷標志;
  • ....

怎么理解中斷標志呢?

“如果被中斷的線程,當前是調用Object#wait、Thread#join、Thread#sleep方法,將收到InterruptedException,并且會清除中斷標志”,案例中的代碼正好符合這點,如果我們將案例代碼改為如下:

  1. @Test 
  2. public void test() { 
  3.     ExecutorService executorService = Executors.newSingleThreadExecutor(); 
  4.     Future<?> future = executorService.submit(() -> { 
  5.         while (!Thread.interrupted()) { 
  6.             System.out.println( "rung....." ); 
  7.             try { 
  8.                 Thread.sleep(1000); 
  9.             } catch (InterruptedException ex) { 
  10.                 System.err.println( "interrupted" ); 
  11.             } 
  12.         } 
  13.     }); 
  14.     ThreadUtils.sleep(1000); 
  15.     future.cancel(true); 
  16.     try { 
  17.         future.get(); 
  18.     } catch (InterruptedException | CancellationException | ExecutionException e) { 
  19.         e.printStackTrace(); 
  20.     } 
  21.     ThreadUtils.sleep(1000 * 60); 

執行這段代碼你會發現,死循環根本沒有退出,正是因為Thread#sleep方法被中斷,JVM并不會設置中斷標志,只是拋出InterruptedException異常。

其它情況下,JVM只會設置中斷標志,并不會拋出InterruptedException。如果我們不處理中斷信號,那么中斷信號并不會影響程序的繼續執行。

  1. @Test 
  2. public void test2() { 
  3.     ExecutorService executorService = Executors.newSingleThreadExecutor(); 
  4.     Future<?> future = executorService.submit(() -> { 
  5.         int number = 0; 
  6.         while (!Thread.interrupted()) { 
  7.             number++; 
  8.         } 
  9.         System.out.println(number); 
  10.     }); 
  11.     ThreadUtils.sleep(1000); 
  12.     future.cancel(true); 
  13.     try { 
  14.         future.get(); 
  15.     } catch (InterruptedException | CancellationException | ExecutionException e) { 
  16.         e.printStackTrace(); 
  17.     } 
  18.     ThreadUtils.sleep(1000 * 60); 

 

此案例并沒有I/O操作導致的阻塞,因為調用中斷方法后,線程只是設置了中斷標志,我們用中斷標志作為循序的退出條件,運行此案例,我們將看到,線程中斷后,任務終止。反之,如果我們不處理中斷標志,那么就等著IDEA進程卡掉吧。

 

責任編輯:武曉燕 來源: Java藝術
相關推薦

2020-11-20 07:51:02

JavaSPI機制

2023-02-24 16:46:25

Glide緩存機制

2024-02-27 08:05:32

Flink分區機制數據傳輸

2015-08-03 09:54:26

Java線程Java

2022-05-06 08:26:32

JavaSPI機制

2022-04-02 08:14:02

JavaThreadLoca數據

2021-09-26 05:06:04

Node.js模塊機制

2024-06-11 09:22:51

2009-07-23 14:08:46

Windows Emb

2025-03-27 02:00:00

SPIJava接口

2025-01-14 10:09:43

硬中斷Linux系統

2021-03-09 08:01:27

CPUarm64寄存器

2020-07-02 22:42:18

Java異常編程

2022-03-11 20:46:01

機制命令kerberos

2021-02-05 08:41:44

STM32網絡中斷

2024-05-11 08:31:20

中斷機制插隊機制React

2023-11-09 11:56:28

MySQL死鎖

2021-08-31 07:54:24

SQLDblink查詢

2024-04-26 00:00:00

Rust檢查器代碼

2021-03-28 08:32:58

Java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久成人精品视频 | 欧美国产视频 | 日韩在线| 综合久久综合久久 | 亚洲一区二区三区免费观看 | 亚洲一区二区三区在线 | 久久久一二三 | 99精品久久 | 欧美日韩一区在线观看 | 亚洲精品v日韩精品 | 国产区免费视频 | 日韩精品一区二区三区中文在线 | 九色porny自拍视频 | 精品福利一区二区三区 | 1204国产成人精品视频 | 在线色网 | 一级黄色裸片 | 激情视频一区 | 国产一区二区在线免费观看 | 国产精品福利在线观看 | 成人精品在线观看 | 午夜在线免费观看 | 手机三级电影 | 亚洲综合二区 | 国产精品a免费一区久久电影 | 午夜小影院 | 国产视频三区 | 日韩精品区 | 国产精品二区三区 | 国产高清美女一级a毛片久久w | 激情av网站 | 中文字幕成人在线 | 久久在线 | 欧美日韩国产三级 | av在线免费观看网站 | 日韩中文在线观看 | 天天操天天摸天天爽 | 欧美成人久久 | 一区二区三区四区在线免费观看 | 在线国产一区 | 精品一区二区三区在线观看 |