偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

聊聊 Java 中的中斷機(jī)制

開發(fā) 后端
在Java中,用于終止一個(gè)正在運(yùn)行中的線程,并非調(diào)用stop方法,而是自行設(shè)置一個(gè)標(biāo)志位,在安全點(diǎn)檢測標(biāo)志位,決定是否退出,但也可能會(huì)因?yàn)榫€程被掛起,無法走到標(biāo)志位。

[[439899]]

在Java中,用于終止一個(gè)正在運(yùn)行中的線程,并非調(diào)用stop方法,而是自行設(shè)置一個(gè)標(biāo)志位,在安全點(diǎn)檢測標(biāo)志位,決定是否退出,但也可能會(huì)因?yàn)榫€程被掛起,無法走到標(biāo)志位。因此,Java線程提供了中斷機(jī)制,Thread類提供了中斷線程執(zhí)行的調(diào)用方法:interrupt,用于中斷因線程掛起的等待,調(diào)用interrupt方法后,線程會(huì)被喚醒,待下次cpu調(diào)度就會(huì)繼續(xù)執(zhí)行中斷后的代碼 。

我們經(jīng)常會(huì)調(diào)用Thread#sleep、Object#wait、Queue#poll等方法,并要求我們處理InterruptedException異常。 那么,拋出InterruptedException后,線程會(huì)終止嗎?

如果不捕獲InterruptedException,那么線程就會(huì)因?yàn)楫惓=K止,是因?yàn)楫惓=K止,并不是因?yàn)楸恢袛?。如果捕獲了InterruptedException,那么線程就不會(huì)終止。

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

xxl-job提供取消任務(wù)操作,而任何運(yùn)行中的線程,都只能利用中斷機(jī)制去結(jié)束線程任務(wù),所以我們想要任務(wù)支持被取消,那么在寫定時(shí)任務(wù)時(shí),一定要考慮清楚,是不是應(yīng)該捕獲InterruptedException,如何利用中斷標(biāo)志結(jié)束任務(wù),否則將會(huì)導(dǎo)致任務(wù)無法被取消。

我們來看個(gè)案例:

  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); 

此案例創(chuàng)建了只有一個(gè)線程的線程池,提交了一個(gè)死循序任務(wù),該任務(wù)只調(diào)用ThreadUtils.sleep方法進(jìn)入休眠。平常我們調(diào)用Thread.sleep方法都要求是否捕獲中斷異常,很多時(shí)候我們都會(huì)嫌棄麻煩,就用一個(gè)工具類提供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.     } 

此案例中,由于我們捕獲了中斷異常,因此這會(huì)導(dǎo)致任務(wù)并不會(huì)被終止,只是當(dāng)我們調(diào)用future的get方法時(shí)會(huì)拋出CancellationException異常,如下圖所示。

任務(wù)依然在運(yùn)行中......

因此,在實(shí)際開發(fā)中,如果我們開發(fā)的Job也是如此,將會(huì)導(dǎo)致Job無法被中斷取消,直至Job執(zhí)行完成或者重啟。在開發(fā)Job時(shí),應(yīng)當(dāng)合理考慮是否要捕獲中斷異常。

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

  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; // 退出死循環(huán) 
  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); 

關(guān)于Thread的interrupt方法,注釋描述的大致意思如下:

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

怎么理解中斷標(biāo)志呢?

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

  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); 

執(zhí)行這段代碼你會(huì)發(fā)現(xiàn),死循環(huán)根本沒有退出,正是因?yàn)門hread#sleep方法被中斷,JVM并不會(huì)設(shè)置中斷標(biāo)志,只是拋出InterruptedException異常。

其它情況下,JVM只會(huì)設(shè)置中斷標(biāo)志,并不會(huì)拋出InterruptedException。如果我們不處理中斷信號(hào),那么中斷信號(hào)并不會(huì)影響程序的繼續(xù)執(zhí)行。

  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操作導(dǎo)致的阻塞,因?yàn)檎{(diào)用中斷方法后,線程只是設(shè)置了中斷標(biāo)志,我們用中斷標(biāo)志作為循序的退出條件,運(yùn)行此案例,我們將看到,線程中斷后,任務(wù)終止。反之,如果我們不處理中斷標(biāo)志,那么就等著IDEA進(jìn)程卡掉吧。

 

責(zé)任編輯:武曉燕 來源: Java藝術(shù)
相關(guān)推薦

2020-11-20 07:51:02

JavaSPI機(jī)制

2023-02-24 16:46:25

Glide緩存機(jī)制

2024-02-27 08:05:32

Flink分區(qū)機(jī)制數(shù)據(jù)傳輸

2015-08-03 09:54:26

Java線程Java

2022-05-06 08:26:32

JavaSPI機(jī)制

2009-07-23 14:08:46

Windows Emb

2022-04-02 08:14:02

JavaThreadLoca數(shù)據(jù)

2025-01-14 10:09:43

硬中斷Linux系統(tǒng)

2021-09-26 05:06:04

Node.js模塊機(jī)制

2024-06-11 09:22:51

2025-03-27 02:00:00

SPIJava接口

2021-03-09 08:01:27

CPUarm64寄存器

2020-07-02 22:42:18

Java異常編程

2022-03-11 20:46:01

機(jī)制命令kerberos

2024-05-11 08:31:20

中斷機(jī)制插隊(duì)機(jī)制React

2021-02-05 08:41:44

STM32網(wǎng)絡(luò)中斷

2021-03-28 08:32:58

Java

2021-02-03 15:12:08

java內(nèi)存溢出

2023-11-09 11:56:28

MySQL死鎖

2024-04-26 00:00:00

Rust檢查器代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)