Java多線程系列--“基礎篇”09之 interrupt()和線程終止方式

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

Java多線程系列--“基礎篇”09之 interrupt()和線程終止方式

概要

本章,會對線程的interrupt()中斷和終止方式進行介紹。涉及到的內容包括:
1. interrupt()說明
2. 終止線程的方式
? 2.1 終止處于“阻塞狀態”的線程
? 2.2 終止處于“運行狀態”的線程
3. 終止線程的示例
4. interrupted() 和 isInterrupted()的區別

轉載請注明出處:http://www.cnblogs.com/skywang12345/p/3479949.html

1. interrupt()說明

在介紹終止線程的方式之前,有必要先對interrupt()進行了解。
關于interrupt(),java的djk文檔描述如下:http://docs.oracle.com/javase/7/docs/api/

  • interrupt()的作用是中斷本線程。
  • 本線程中斷自己是被允許的;其它線程調用本線程的interrupt()方法時,會通過checkAccess()檢查權限。這有可能拋出SecurityException異常。
  • 如果本線程是處于阻塞狀態:調用線程的wait(), wait(long)或wait(long, int)會讓它進入等待(阻塞)狀態,或者調用線程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會讓它進入阻塞狀態。若線程在阻塞狀態時,調用了它的interrupt()方法,那么它的“中斷狀態”會被清除并且會收到一個InterruptedException異常。例如,線程通過wait()進入阻塞狀態,此時通過interrupt()中斷該線程;調用interrupt()會立即將線程的中斷標記設為“true”,但是由于線程處于阻塞狀態,所以該“中斷標記”會立即被清除為“false”,同時,會產生一個InterruptedException的異常。
  • 如果線程被阻塞在一個Selector選擇器中,那么通過interrupt()中斷它時;線程的中斷標記會被設置為true,并且它會立即從選擇操作中返回。
  • 如果不屬于前面所說的情況,那么通過interrupt()中斷線程時,它的中斷標記會被設置為“true”。
  • 中斷一個“已終止的線程”不會產生任何操作。

2. 終止線程的方式

Thread中的stop()和suspend()方法,由于固有的不安全性,已經建議不再使用!
下面,我先分別討論線程在“阻塞狀態”和“運行狀態”的終止方式,然后再總結出一個通用的方式。

2.1 終止處于“阻塞狀態”的線程

通常,我們通過“中斷”方式終止處于“阻塞狀態”的線程。
當線程由于被調用了sleep(), wait(), join()等方法而進入阻塞狀態;若此時調用線程的interrupt()將線程的中斷標記設為true。由于處于阻塞狀態,中斷標記會被清除,同時產生一個InterruptedException異常。將InterruptedException放在適當的位置就能終止線程,形式如下:

@Override
public void run() {try {while (true) {// 執行任務...}} catch (InterruptedException ie) {  // 由于產生InterruptedException異常,退出while(true)循環,線程終止!}
}

說明:在while(true)中不斷的執行任務,當線程處于阻塞狀態時,調用線程的interrupt()產生InterruptedException中斷。中斷的捕獲在while(true)之外,這樣就退出了while(true)循環!
注意:對InterruptedException的捕獲務一般放在while(true)循環體的外面,這樣,在產生異常時就退出了while(true)循環。否則,InterruptedException在while(true)循環體之內,就需要額外的添加退出處理。形式如下

@Override
public void run() {while (true) {try {// 執行任務...} catch (InterruptedException ie) {  // InterruptedException在while(true)循環體內。// 當線程產生了InterruptedException異常時,while(true)仍能繼續運行!需要手動退出break;}}
}

說明:上面的InterruptedException異常的捕獲在whle(true)之內。當產生InterruptedException異常時,被catch處理之外,仍然在while(true)循環體內;要退出while(true)循環體,需要額外的執行退出while(true)的操作。

2.2 終止處于“運行狀態”的線程

通常,我們通過“標記”方式終止處于“運行狀態”的線程。其中,包括“中斷標記”和“額外添加標記”。
(01) 通過“中斷標記”終止線程。
形式如下:

@Override
public void run() {while (!isInterrupted()) {// 執行任務...}
}

說明:isInterrupted()是判斷線程的中斷標記是不是為true。當線程處于運行狀態,并且我們需要終止它時;可以調用線程的interrupt()方法,使用線程的中斷標記為true,即isInterrupted()會返回true。此時,就會退出while循環。
注意:interrupt()并不會終止處于“運行狀態”的線程!它會將線程的中斷標記設為true。

(02) 通過“額外添加標記”。
形式如下:

private volatile boolean flag= true;
protected void stopTask() {flag = false;
}@Override
public void run() {while (flag) {// 執行任務...}
}

說明:線程中有一個flag標記,它的默認值是true;并且我們提供stopTask()來設置flag標記。當我們需要終止該線程時,調用該線程的stopTask()方法就可以讓線程退出while循環。
注意:將flag定義為volatile類型,是為了保證flag的可見性。即其它線程通過stopTask()修改了flag之后,本線程能看到修改后的flag的值。

綜合線程處于“阻塞狀態”和“運行狀態”的終止方式,比較通用的終止線程的形式如下:

@Override
public void run() {try {// 1. isInterrupted()保證,只要中斷標記為true就終止線程。while (!isInterrupted()) {// 執行任務...}} catch (InterruptedException ie) {  // 2. InterruptedException異常保證,當InterruptedException異常產生時,線程被終止。}
}

3. 終止線程的示例

interrupt()常常被用來終止“阻塞狀態”線程。參考下面示例:

// Demo1.java的源碼
class MyThread extends Thread {public MyThread(String name) {super(name);}@Overridepublic void run() {try {  int i=0;while (!isInterrupted()) {Thread.sleep(100); // 休眠100msi++;System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  }} catch (InterruptedException e) {  System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  }}
}public class Demo1 {public static void main(String[] args) {  try {  Thread t1 = new MyThread("t1");  // 新建“線程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  t1.start();                      // 啟動“線程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  // 主線程休眠300ms,然后主線程給t1發“中斷”指令。Thread.sleep(300);t1.interrupt();System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");// 主線程休眠300ms,然后查看t1的狀態。Thread.sleep(300);System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");} catch (InterruptedException e) {  e.printStackTrace();}} 
}
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.

結果說明
(01) 主線程main中通過new MyThread("t1")創建線程t1,之后通過t1.start()啟動線程t1。
(02) t1啟動之后,會不斷的檢查它的中斷標記,如果中斷標記為“false”;則休眠100ms。
(03) t1休眠之后,會切換到主線程main;主線程再次運行時,會執行t1.interrupt()中斷線程t1。t1收到中斷指令之后,會將t1的中斷標記設置“false”,而且會拋出InterruptedException異常。在t1的run()方法中,是在循環體while之外捕獲的異常;因此循環被終止。

我們對上面的結果進行小小的修改,將run()方法中捕獲InterruptedException異常的代碼塊移到while循環體內。

// Demo2.java的源碼
class MyThread extends Thread {public MyThread(String name) {super(name);}@Overridepublic void run() {int i=0;while (!isInterrupted()) {try {Thread.sleep(100); // 休眠100ms} catch (InterruptedException ie) {  System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  }i++;System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  }}
}public class Demo2 {public static void main(String[] args) {  try {  Thread t1 = new MyThread("t1");  // 新建“線程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  t1.start();                      // 啟動“線程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  // 主線程休眠300ms,然后主線程給t1發“中斷”指令。Thread.sleep(300);t1.interrupt();System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");// 主線程休眠300ms,然后查看t1的狀態。Thread.sleep(300);System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");} catch (InterruptedException e) {  e.printStackTrace();}} 
}
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (RUNNABLE) loop 3
t1 (RUNNABLE) loop 4
t1 (RUNNABLE) loop 5
t1 (TIMED_WAITING) is interrupted now.
t1 (RUNNABLE) loop 6
t1 (RUNNABLE) loop 7
t1 (RUNNABLE) loop 8
t1 (RUNNABLE) loop 9
...

結果說明
程序進入了死循環!
為什么會這樣呢?這是因為,t1在“等待(阻塞)狀態”時,被interrupt()中斷;此時,會清除中斷標記[即isInterrupted()會返回false],而且會拋出InterruptedException異常[該異常在while循環體內被捕獲]。因此,t1理所當然的會進入死循環了。
解決該問題,需要我們在捕獲異常時,額外的進行退出while循環的處理。例如,在MyThread的catch(InterruptedException)中添加break 或 return就能解決該問題。

下面是通過“額外添加標記”的方式終止“狀態狀態”的線程的示例:

// Demo3.java的源碼
class MyThread extends Thread {private volatile boolean flag= true;public void stopTask() {flag = false;}public MyThread(String name) {super(name);}@Overridepublic void run() {synchronized(this) {try {int i=0;while (flag) {Thread.sleep(100); // 休眠100msi++;System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  }} catch (InterruptedException ie) {  System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  }}  }
}public class Demo3 {public static void main(String[] args) {  try {  MyThread t1 = new MyThread("t1");  // 新建“線程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  t1.start();                      // 啟動“線程t1”System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  // 主線程休眠300ms,然后主線程給t1發“中斷”指令。Thread.sleep(300);t1.stopTask();System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");// 主線程休眠300ms,然后查看t1的狀態。Thread.sleep(300);System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");} catch (InterruptedException e) {  e.printStackTrace();}} 
}
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) loop 3
t1 (TERMINATED) is interrupted now.

4. interrupted() 和 isInterrupted()的區別

最后談談 interrupted() 和 isInterrupted()。
interrupted() 和 isInterrupted()都能夠用于檢測對象的“中斷標記”。
區別是,interrupted()除了返回中斷標記之外,它還會清除中斷標記(即將中斷標記設為false);而isInterrupted()僅僅返回中斷標記。

?

?

?

?

轉載于:https://my.oschina.net/LucasZhu/blog/1529532

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540674.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mac活動監視器_什么是活動監視器?

mac活動監視器活動監控 (Activity Monitor) Apple OS X provides the services of which one of them is Activity Monitor. Activity Monitor is used to monitor the activities of computer like active processes, processor load, applications that are running, and the…

concurrent包下的Exchanger練習

Exchanger可以在兩個線程之間交換數據,只能是2個線程,他不支持更多的線程之間互換數據。 當線程A調用Exchange對象的exchange()方法后,他會陷入阻塞狀態,直到線程B也調用了exchange()方法,然后以線程安全的方式交換數據…

Python默認參數

Python | 默認參數 (Python | default parameters) A default parameter is a value provided in a function declaration that is automatically assigned by the compiler if the caller of the function doesnt provide a value for the parameter with the default value. …

最長公共前綴_最長的公共前綴

最長公共前綴Problem statement: 問題陳述: Write a function to find the longest common prefix string amongst an array of strings. 編寫函數以在字符串數組中找到最長的公共前綴字符串 。 If there is no common prefix, return an empty string "&quo…

物聯網聽起來像是一個和互聯網不同的網,萬物互聯又把網給弄丟了,正向我們撲面而來的是萬物互聯網。...

物聯網聽起來像是一個和互聯網不同的網,"萬物互聯"又把"網"給弄丟了,正向我們撲面而來的是"萬物互聯網"。轉載于:https://www.cnblogs.com/beingonline/p/7484135.html

sdram trp_TRP的完整形式是什么?

sdram trpTRP:電視收視點 (TRP: Television Rating Point) TRP is an abbreviation of "Television Rating Point". TRP是“電視評分點”的縮寫 。 It is a system or standard of measurement which signifies the demand and popularity of a televisi…

Controller計算值傳到jsp頁面,用session傳值

HttpSession session request.getSession(); session.setAttribute("key",value); jap 用 ${key}來接收該值 轉載于:https://www.cnblogs.com/douder/p/7484491.html

CBT的完整形式是什么?

CBT:基于計算機的培訓 (CBT: Computer Based Training) CBT is an abbreviation of "Computer-based training". CBT是“基于計算機的培訓”的縮寫 。 It is a training program which entails the use of a personal system or networked computer. The…

論道社會化商業

主持人 用友優普副總裁傅毅: 謝謝各位嘉賓,我們會留一些時間讓在座的嘉賓提問。請各位嘉賓用一個非常簡單的一句話,或者幾個關鍵詞,總結一下你認為的社會化商業是什么? 用友優普執行總裁 徐洋: 社會化商業為…

CChelper彩虹SDK可視遠程客服解決方案

本文講的是 : CChelper彩虹SDK可視遠程客服解決方案 , 在智能生態產業鏈中,智能硬件終端是把握消費者的直接環節,隨著物聯網時代邁向成熟,智能家居領域的硬件逐漸成為智能硬件終端的主角。目前的市場環境下,智能家居領域的自身硬…

matlab 簡介_MATLAB簡介

matlab 簡介MATLAB簡介 (MATLAB Introduction) MATLAB was designed by Cleve Moler for his student in 1970s but after some time jack little, an engineer realized its potential and rewrote it at the MathWorks, and it was rewritten in C language by the date of 1…

Scala中的嵌套循環

Scala中的嵌套循環 (Nested loop in Scala) In programming, a nested loop is used in initializing or iterate multi-dimensional array or to print patterns. Scala provides an efficient method to use nested loops in the programming language. The most used nested…

python基礎-字典

字典 # 字典是python基本數據結構之一,相對于列表和元組,他是無序的,每次輸出都打亂了順序,沒有下標hello{110:{"name":"alex","age":28,"home":"shandong"},111:{"name&…

sql算術運算符_SQL中的算術運算符

sql算術運算符SQL | 算術運算符 (SQL | Arithmetic Operators) Different number-crunching administrators are utilized in SQL to be specific Addition (), Subtraction (-), Multiplication (*), Division (/), Modulus (%). SQL中使用了不同的數字運算管理員來表示特定的…

HDU 6188 Duizi and Shunzi

棧。 將數字排序后&#xff0c;一個一個壓入棧。如果棧頂兩個元素形成了對子&#xff0c;那么$ans1$&#xff0c;彈出棧頂兩個元素&#xff1b;如果棧頂三個元素形成了順子&#xff0c;那么$ans1$&#xff0c;彈出棧頂三個元素。 #include<bits/stdc.h> using namespace …

php 單例模式有什么缺點_PHP的完整形式是什么?

php 單例模式有什么缺點PHP&#xff1a;超文本預處理器 (PHP: Hypertext Preprocessor ) PHP is an abbreviation of Hypertext Preprocessor, earlier called Personal Home Page. PHP is extensively used HTML-embedded, open-source server-side scripting language create…

Myeclipse有關的問題

Myeclipse配置問題 1.行數顯示 window ----preference----General-----Editors-----TextEditors----show line numbers 2.編碼設置 window ---preference----workspace-----設置 3.jsp編碼設置 window ---preference----myeclipse------Files And Editors------jsp 4.jsp的視圖…

weak-to-strong-generalization始終比母體更智能的人工智能,能否被它的母體所監管supervision,從而變的更強

正如supervison這個詞&#xff0c;就像就是母親對孩子的超級super愿景vision&#xff0c;比母親更聰明更強&#xff0c;也就意味著要按照母親期望的那樣成長&#xff0c;不合理的行為要能夠糾正supervison。 一代比一代強&#xff0c;一代比一代好。 弱模型監督能否激發出更強…

最小跳數

Description: 描述&#xff1a; This problem is a standard interview problem which has been featured in interview rounds of Adobe, Amazon, Oyo rooms etc. 此問題是標準的采訪問題&#xff0c;已在Adobe&#xff0c;Amazon&#xff0c;Oyo房間等的采訪回合中出現。 P…

《Web安全之機器學習入門》一 第3章 機器學習概述

第3章 機器學習概述機器學習的概念非常多&#xff0c;從有監督到無監督&#xff0c;從聚類到回歸&#xff0c;從淺層學習到深度學習&#xff0c;從準確率到召回率&#xff0c;它們究竟是什么意思呢&#xff1f;本章將介紹最主要的幾個概念。不少機器學習初學者甚至包括業內老司…