日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
為什么說(shuō)Volatile+Interrupt是停止線(xiàn)程優(yōu)雅的姿勢(shì)?

使用stop方法

調(diào)用stop方法,會(huì)讓正在運(yùn)行的線(xiàn)程直接中止,有可能會(huì)讓一些清理性的工作得不到完成。并且stop已經(jīng)被標(biāo)記為廢棄的方法,不建議使用。

正確的使用姿勢(shì)是使用兩階段終止的模式,即一個(gè)線(xiàn)程發(fā)送終止指令,另一個(gè)線(xiàn)程接收指令,并且決定自己在何時(shí)停止。

使用標(biāo)志位

 
 
 
 
  1. public class RunTask { 
  2.  
  3.     private volatile boolean stopFlag; 
  4.     private Thread taskThread; 
  5.  
  6.     public void start() { 
  7.         taskThread = new Thread(() -> { 
  8.             while (!stopFlag) { 
  9.                 System.out.println("doSomething"); 
  10.             } 
  11.         }); 
  12.         taskThread.start(); 
  13.     } 
  14.  
  15.     public void stop() { 
  16.         stopFlag = true; 
  17.     } 

「stopFlag上加volatile是保證可見(jiàn)性。我這個(gè)例子用了while循環(huán)不斷判斷,如果項(xiàng)目中用不到while的話(huà),可以在關(guān)鍵節(jié)點(diǎn)判斷,然后退出run方法即可」

使用interrupt方法

假如我們的任務(wù)中有阻塞的邏輯,如調(diào)用了Thread.sleep方法,如何讓線(xiàn)程停止呢?

從線(xiàn)程狀態(tài)轉(zhuǎn)換圖中尋找答案

從圖中可以看到如果想讓線(xiàn)程進(jìn)入終止?fàn)顟B(tài)的前提是這個(gè)線(xiàn)程處于運(yùn)行狀態(tài)。當(dāng)我們想要終止一個(gè)線(xiàn)程的時(shí)候,如果此時(shí)線(xiàn)程處于阻塞狀態(tài),我們?nèi)绾伟阉D(zhuǎn)換到運(yùn)行狀態(tài)呢?

我們可以通過(guò)調(diào)用Thread#interrupt方法,將阻塞狀態(tài)的線(xiàn)程轉(zhuǎn)換到就緒狀態(tài),進(jìn)入由操作系統(tǒng)調(diào)度成運(yùn)行狀態(tài),即可終止。

那線(xiàn)程在運(yùn)行狀態(tài)中調(diào)用interrupt方法,會(huì)發(fā)生什么呢?

 
 
 
 
  1. public class RunTaskCase1 { 
  2.  
  3.     private Thread taskThread; 
  4.  
  5.     public void start() { 
  6.         taskThread = new Thread(() -> { 
  7.             while (true) { 
  8.                 System.out.println("doSomething"); 
  9.             } 
  10.         }); 
  11.         taskThread.start(); 
  12.     } 
  13.  
  14.     public void stop() { 
  15.         taskThread.interrupt(); 
  16.     } 

依次調(diào)用start方法和stop方法,發(fā)現(xiàn)線(xiàn)程并沒(méi)有停止。

「其實(shí)當(dāng)線(xiàn)程處于運(yùn)行狀態(tài)時(shí),interrupt方法只是在當(dāng)前線(xiàn)程打了一個(gè)停止的標(biāo)記,停止的邏輯需要我們自己去實(shí)現(xiàn)」

「Thread類(lèi)提供了如下2個(gè)方法來(lái)判斷線(xiàn)程是否是中斷狀態(tài)」

  1. isInterrupted
  2. interrupted

這2個(gè)方法雖然都能判斷狀態(tài),但是有細(xì)微的差別

 
 
 
 
  1. @Test 
  2. public void testInterrupt() throws InterruptedException { 
  3.     Thread thread = new Thread(() -> { 
  4.         while (true) {} 
  5.     }); 
  6.     thread.start(); 
  7.     TimeUnit.MICROSECONDS.sleep(100); 
  8.     thread.interrupt(); 
  9.     // true 
  10.     System.out.println(thread.isInterrupted()); 
  11.     // true 
  12.     System.out.println(thread.isInterrupted()); 
  13.     // true 
  14.     System.out.println(thread.isInterrupted()); 
 
 
 
 
  1. @Test 
  2. public void testInterrupt2() { 
  3.     Thread.currentThread().interrupt(); 
  4.     // true 
  5.     System.out.println(Thread.interrupted()); 
  6.     // false 
  7.     System.out.println(Thread.interrupted()); 
  8.     // false 
  9.     System.out.println(Thread.interrupted()); 

「isInterrupted和interrupted的方法區(qū)別如下」

Thread#isInterrupted:測(cè)試線(xiàn)程是否是中斷狀態(tài),執(zhí)行后不更改狀態(tài)標(biāo)志 Thread#interrupted:測(cè)試線(xiàn)程是否是中斷狀態(tài),執(zhí)行后將中斷標(biāo)志更改為false

「所以此時(shí)我們不需要自已定義狀態(tài),直接用中斷標(biāo)志即可,之前的代碼可以改為如下」

 
 
 
 
  1. public class RunTaskCase2 { 
  2.  
  3.     private Thread taskThread; 
  4.  
  5.     public void start() { 
  6.         taskThread = new Thread(() -> { 
  7.             while (!Thread.currentThread().isInterrupted()) { 
  8.                 System.out.println("doSomething"); 
  9.             } 
  10.         }); 
  11.         taskThread.start(); 
  12.     } 
  13.  
  14.     public void stop() { 
  15.         taskThread.interrupt(); 
  16.     } 

當(dāng)線(xiàn)程處于阻塞狀態(tài)時(shí),調(diào)用interrupt方法,會(huì)拋出InterruptedException,也能終止線(xiàn)程的執(zhí)行

「注意:發(fā)生異常時(shí)線(xiàn)程的中斷標(biāo)志為會(huì)由true更改為false?!?/strong>

所以我們有如下實(shí)現(xiàn) 當(dāng)線(xiàn)程處于運(yùn)行狀態(tài):用自己定義的標(biāo)志位來(lái)退出 當(dāng)線(xiàn)程處于阻塞狀態(tài):用拋異常的方式來(lái)退出

 
 
 
 
  1. public class RunTaskCase3 { 
  2.  
  3.     private volatile boolean stopFlag; 
  4.     private Thread taskThread; 
  5.  
  6.     public void start() { 
  7.         taskThread = new Thread(() -> { 
  8.             while (stopFlag) { 
  9.                 try { 
  10.                     System.out.println("doSomething"); 
  11.                     TimeUnit.MICROSECONDS.sleep(100); 
  12.                 } catch (InterruptedException e) { 
  13.                     e.printStackTrace(); 
  14.                 } 
  15.             } 
  16.         }); 
  17.         taskThread.start(); 
  18.     } 
  19.  
  20.     public void stop() { 
  21.         stopFlag = true; 
  22.         taskThread.interrupt(); 
  23.     } 

當(dāng)然也可以一直用中斷標(biāo)志來(lái)退出,「注意,當(dāng)發(fā)生異常的時(shí)候需要重置中斷標(biāo)志位」。

 
 
 
 
  1. public class RunTaskCase4 { 
  2.  
  3.     private Thread taskThread; 
  4.  
  5.     public void start() { 
  6.         taskThread = new Thread(() -> { 
  7.             while (!Thread.currentThread().isInterrupted()) { 
  8.                 try { 
  9.                     System.out.println("doSomething"); 
  10.                     TimeUnit.MICROSECONDS.sleep(100); 
  11.                 } catch (InterruptedException e) { 
  12.                     // 重置中斷標(biāo)志位為true 
  13.                     Thread.currentThread().interrupt(); 
  14.                     e.printStackTrace(); 
  15.                 } 
  16.             } 
  17.         }); 
  18.         taskThread.start(); 
  19.     } 
  20.  
  21.     public void stop() { 
  22.         taskThread.interrupt(); 
  23.     } 

最后問(wèn)大家一個(gè)問(wèn)題?RunTaskCase3和RunTaskCase4哪種實(shí)現(xiàn)方式比較好呢?

「雖然RunTaskCase4代碼看起來(lái)更簡(jiǎn)潔,但是RunTaskCase4不建議使用,因?yàn)槿绻趓un方法中調(diào)用了第三方類(lèi)庫(kù),發(fā)生了InterruptedException異常,但是沒(méi)有重置中斷標(biāo)志位,會(huì)導(dǎo)致線(xiàn)程一直運(yùn)行下去,同理RunTaskCase2也不建議使用」。

本文轉(zhuǎn)載自微信公眾號(hào)「 Java識(shí)堂」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 Java識(shí)堂公眾號(hào)。


名稱(chēng)欄目:為什么說(shuō)Volatile+Interrupt是停止線(xiàn)程優(yōu)雅的姿勢(shì)?
本文來(lái)源:http://m.5511xx.com/article/ccdceoj.html