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

為什么說Volatile+Interrupt是停止線程優(yōu)雅的姿勢?

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

[[383078]]

使用stop方法

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

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

使用標(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是保證可見性。我這個例子用了while循環(huán)不斷判斷,如果項目中用不到while的話,可以在關(guān)鍵節(jié)點判斷,然后退出run方法即可」

使用interrupt方法

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

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

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

 

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

那線程在運行狀態(tài)中調(diào)用interrupt方法,會發(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)線程并沒有停止。

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

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

  1. isInterrupted
  2. interrupted

這2個方法雖然都能判斷狀態(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:測試線程是否是中斷狀態(tài),執(zhí)行后不更改狀態(tài)標(biāo)志 Thread#interrupted:測試線程是否是中斷狀態(tài),執(zhí)行后將中斷標(biāo)志更改為false

「所以此時我們不需要自已定義狀態(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)線程處于阻塞狀態(tài)時,調(diào)用interrupt方法,會拋出InterruptedException,也能終止線程的執(zhí)行

「注意:發(fā)生異常時線程的中斷標(biāo)志為會由true更改為false。」

所以我們有如下實現(xiàn) 當(dāng)線程處于運行狀態(tài):用自己定義的標(biāo)志位來退出 當(dāng)線程處于阻塞狀態(tà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)志來退出,「注意,當(dāng)發(fā)生異常的時候需要重置中斷標(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.     } 

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

「雖然RunTaskCase4代碼看起來更簡潔,但是RunTaskCase4不建議使用,因為如果在run方法中調(diào)用了第三方類庫,發(fā)生了InterruptedException異常,但是沒有重置中斷標(biāo)志位,會導(dǎo)致線程一直運行下去,同理RunTaskCase2也不建議使用」。

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

 

責(zé)任編輯:武曉燕 來源: Java識堂
相關(guān)推薦

2023-09-18 08:01:06

Spring管理Mybatis

2022-03-14 08:33:09

TypeScriptJavaScript前端

2020-07-03 14:05:26

Serverless云服務(wù)商

2021-11-29 18:27:12

Web Wasmjs

2019-09-23 13:37:09

Anthos谷歌Kubernetes

2011-09-20 15:51:42

NoSQL

2011-10-27 13:37:51

網(wǎng)頁設(shè)計

2023-05-05 16:26:33

2019-09-23 13:10:02

容器進(jìn)程

2019-01-18 15:01:17

云計算運維管理

2023-03-21 10:16:36

2023-05-04 07:44:13

編程界小語言Java

2021-02-25 14:09:55

人工智能數(shù)據(jù)機(jī)器學(xué)習(xí)

2018-01-23 11:48:17

Vue.js前端開發(fā)

2021-01-14 15:34:53

區(qū)塊鏈比特幣機(jī)器

2012-02-08 10:02:53

Web

2025-05-27 10:10:00

Java緩存開發(fā)

2011-05-05 08:51:18

PHP

2025-04-07 08:30:00

緩存Java開發(fā)

2023-01-03 19:11:09

CPUI/O速度
點贊
收藏

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

主站蜘蛛池模板: 亚洲成人一二区 | 一级a爱片久久毛片 | 日韩欧美一区二区三区 | 一a级片| 国产精品久久久久久网站 | 中文字幕av一区二区三区 | 在线黄 | 日韩免费视频一区二区 | 影音先锋男 | 韩国毛片一区二区三区 | 亚洲激情综合网 | 中文字幕 在线观看 | 欧美国产日本一区 | 亚洲精品电影在线 | 国产这里只有精品 | 天天操天天射天天 | 久久电影一区 | 99亚洲 | 国产高清精品一区二区三区 | 亚洲福利视频一区二区 | 成人国产精品久久 | 精品国产一区二区在线 | 精品网站999www | 一区二区在线不卡 | 欧美视频一区二区三区 | 日本激情视频中文字幕 | 精品99久久久久久 | 手机在线观看 | 天堂成人国产精品一区 | 日韩精品一区在线 | 国产99精品 | 一二三四在线视频观看社区 | 亚洲一区二区av | 日本高清不卡视频 | 欧美性久久久 | 免费国产视频 | 亚洲va欧美va天堂v国产综合 | 欧美日韩在线观看一区二区三区 | 国产第一页在线播放 | 老司机精品福利视频 | 国产成人免费视频网站高清观看视频 |