最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入分析JAVA 多線程--interrupt()和線程終止方式

 更新時(shí)間:2020年06月23日 09:21:48   作者:凌傾-學(xué)無止境  
這篇文章主要介紹了JAVA 多線程--interrupt()和線程終止方式的的相關(guān)資料,文中代碼非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

一、interrupt() 介紹

interrupt() 定義在 Thread 類中,作用是中斷本線程。

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

二、線程終止方式

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

(一)、終止處于“阻塞狀態(tài)”的線程.

通常,我們通過“中斷”方式終止處于“阻塞狀態(tài)”的線程。
當(dāng)線程由于被調(diào)用了 sleep(),,wait(),join() 等方法而進(jìn)入阻塞狀態(tài);若此時(shí)調(diào)用線程的 interrupt() 將線程的中斷標(biāo)記設(shè)為 true。由于處于阻塞狀態(tài),中斷標(biāo)記會(huì)被清除,同時(shí)產(chǎn)生一個(gè)InterruptedException 異常。將 InterruptedException 放在適當(dāng)?shù)奈恢镁湍芙K止線程,形式如下:

public void run() {
  try {
    while (true) {
      // 執(zhí)行業(yè)務(wù)
    }
  } catch (InterruptedException ie) { 
    // 由于產(chǎn)生InterruptedException異常,退出while(true)循環(huán),線程終止!
  }
}

說明:

在while(true)中不斷的執(zhí)行業(yè)務(wù)代碼,當(dāng)線程處于阻塞狀態(tài)時(shí),調(diào)用線程的 interrupt() 產(chǎn)生 InterruptedException 中斷。中斷的捕獲在 while(true) 之外,這樣就退出了 while(true) 循環(huán)!

注意:

對 InterruptedException 的捕獲務(wù)一般放在 while(true) 循環(huán)體的外面,這樣,在產(chǎn)生異常時(shí)就退出了 while(true) 循環(huán)。否則,InterruptedException 在 while(true) 循環(huán)體之內(nèi),就需要額外的添加退出處理形式如下:

public void run() {
  while (true) {
    try {
      // 執(zhí)行任務(wù)...
    } catch (InterruptedException ie) { 
      // InterruptedException在while(true)循環(huán)體內(nèi)。
      // 當(dāng)線程產(chǎn)生了InterruptedException異常時(shí),while(true)仍能繼續(xù)運(yùn)行!需要手動(dòng)退出
      break;
    }
  }
}

說明:

上面的 InterruptedException 異常的捕獲在 whle(true) 之內(nèi)。當(dāng)產(chǎn)生 InterruptedException 異常時(shí),被 catch 處理之外,仍然在 while(true) 循環(huán)體內(nèi);要退出 while(true) 循環(huán)體,需要額外的執(zhí)行退出while(true) 的操作。

(二)、終止處于“運(yùn)行狀態(tài)”的線程

通常,我們通過“標(biāo)記”方式終止處于“運(yùn)行狀態(tài)”的線程。其中,包括“中斷標(biāo)記”和“額外添加標(biāo)記”。

1、通過“中斷標(biāo)記”終止線程

public void run() {
  while (!isInterrupted()) {
    // 執(zhí)行任務(wù)...
  }
}

說明:

isInterrupted() 是判斷線程的中斷標(biāo)記是不是為 true。當(dāng)線程處于運(yùn)行狀態(tài),并且我們需要終止它時(shí);可以調(diào)用線程的 interrupt() 方法,使用線程的中斷標(biāo)記為 true,即 isInterrupted() 會(huì)返回true。此時(shí),就會(huì)退出while循環(huán)。

注意:interrupt() 并不會(huì)終止處于“運(yùn)行狀態(tài)”的線程!它會(huì)將線程的中斷標(biāo)記設(shè)為 true。

2、通過“額外添加標(biāo)記”終止線程

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

說明:

線程中有一個(gè) flag 標(biāo)記,它的默認(rèn)值是 true;并且我們提供 stopTask() 來設(shè)置 flag 標(biāo)記。當(dāng)我們需要終止該線程時(shí),調(diào)用該線程的 stopTask() 方法就可以讓線程退出 while 循環(huán)。

注意:將 flag 定義為 volatile 類型,是為了保證 flag 的可見性。即其它線程通過 stopTask() 修改了 flag 之后,本線程能看到修改后的 flag 的值。

(三)、通過方式

綜合線程處于“阻塞狀態(tài)”和“運(yùn)行狀態(tài)”的終止方式,比較通用的終止線程的形式如下:

public void run() {
  try {
    // 1. isInterrupted()保證,只要中斷標(biāo)記為true就終止線程。
    while (!isInterrupted()) {
      // 執(zhí)行任務(wù)...
    }
  } catch (InterruptedException ie) { 
    // 2. InterruptedException異常保證,當(dāng)InterruptedException異常產(chǎn)生時(shí),線程被終止。
  }
}

1、isInterrupted()保證,只要中斷標(biāo)記為 true 就終止線程。
2、InterruptedException 異常保證,當(dāng) InterruptedException 異常產(chǎn)生時(shí),線程被終止。

三、示例

public class InterruptTest {
  public static void main(String[] args) {
    try {
      Thread t1 = new MyThread("t1"); // 新建線程t1
      System.out.println(t1.getName() + "[" + t1.getState() + "] is new.");
      
      t1.start();// 啟動(dòng)線程t1
      System.out.println(t1.getName() + "[" + t1.getState() + "] is started.");
      
      Thread.sleep(300);// 休眠300毫秒,然后主線程給t1發(fā)“中斷”指令,查看t1狀態(tài)
      t1.interrupt();
      System.out.println(t1.getName() + "[" + t1.getState() + "] is interrupted.");
      
      Thread.sleep(300);// 休眠300毫秒,然后查看t1狀態(tài)
      System.out.println(t1.getName() + "[" + t1.getState() + "] is interrupted now.");
    }catch(InterruptedException e) {
      e.printStackTrace();
    }
  }
}
class MyThread extends Thread{
  public MyThread(String name) {
    super(name);
  }
  @Override
  public void run() {
    try {
      int i = 0;
      while(!isInterrupted()) {
        Thread.sleep(100);// 休眠100毫秒
        ++i;
        System.out.println(Thread.currentThread().getName() + "[" + this.getState() + "] loop " + i);
      }
    }catch(InterruptedException e) {
      System.out.println(Thread.currentThread().getName() + "[" + this.getState() + "] catch InterruptedException");
    }
  }
}

運(yùn)行結(jié)果

t1 [ NEW ] is new.
t1 [ RUNNABLE ] is started.
t1 [ RUNNABLE ] loop 1
t1 [ RUNNABLE ] loop 2
t1 [ RUNNABLE ] loop 3
t1 [ RUNNABLE ] catch InterruptedException
t1 [ TERMINATED ] is interrupted.
t1 [ TERMINATED ] is interrupted now.

說明:

①、主線程 main 中通過 new MyThread("t1") 創(chuàng)建線程 t1,之后通過 t1.start() 啟動(dòng)線程 t1。

②、t1 啟動(dòng)之后,會(huì)不斷的檢查它的中斷標(biāo)記,如果中斷標(biāo)記為“false”;則休眠 100ms。

③、t1 休眠之后,會(huì)切換到主線程main;主線程再次運(yùn)行時(shí),會(huì)執(zhí)行t1.interrupt()中斷線程t1。t1收到中斷指令之后,會(huì)將t1的中斷標(biāo)記設(shè)置“false”,而且會(huì)拋出 InterruptedException 異常。在 t1 的 run() 方法中,是在循環(huán)體 while 之外捕獲的異常;因此循環(huán)被終止。

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

public class InterruptTest {
  public static void main(String[] args) {
    try {
      Thread t1 = new MyThread("t1"); // 新建線程t1
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is new.");
      
      t1.start();// 啟動(dòng)線程t1
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is started.");
      
      Thread.sleep(300);// 休眠300毫秒,然后主線程給t1發(fā)“中斷”指令,查看t1狀態(tài)
      t1.interrupt();
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is interrupted.");
      
      Thread.sleep(300);// 休眠300毫秒,然后查看t1狀態(tài)
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is interrupted now.");
    }catch(InterruptedException e) {
      e.printStackTrace();
    }
    
  }
}
class MyThread extends Thread{
  public MyThread(String name) {
    super(name);
  }
  @Override
  public 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); 
    }
  }
}

運(yùn)行結(jié)果

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 [ RUNNABLE ] loop 6
t1 [ RUNNABLE ] is interrupted now.
t1 [ RUNNABLE ] loop 7
...... // 無限循環(huán)

說明:

程序進(jìn)入了死循環(huán)了。

這是因?yàn)?,t1在“等待(阻塞)狀態(tài)”時(shí),被 interrupt() 中斷;此時(shí),會(huì)清除中斷標(biāo)記(即 isInterrupted() 會(huì)返回 false),而且會(huì)拋出 InterruptedException 異常(該異常在while循環(huán)體內(nèi)被捕獲)。因此,t1理所當(dāng)然的會(huì)進(jìn)入死循環(huán)了。

解決該問題,需要我們在捕獲異常時(shí),額外的進(jìn)行退出 while 循環(huán)的處理。例如,在 MyThread 的 catch(InterruptedException) 中添加 break 或 return 就能解決該問題。

下面是通過“額外添加標(biāo)記”的方式終止“狀態(tài)狀態(tài)”的線程的示例:

public class InterruptTest {
  public static void main(String[] args) {
    try {
      MyThread t1 = new MyThread("t1"); // 新建線程t1
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is new.");
      
      t1.start();// 啟動(dòng)線程t1
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is started.");
      
      Thread.sleep(300);// 休眠300毫秒,然后主線程給t1發(fā)“中斷”指令,查看t1狀態(tài)
      t1.stopTask();
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is interrupted.");
      
      Thread.sleep(300);// 休眠300毫秒,然后查看t1狀態(tài)
      System.out.println(t1.getName() + " [ " + t1.getState() + " ] is interrupted now.");
    }catch(InterruptedException e) {
      e.printStackTrace();
    }
    
  }
}
class MyThread extends Thread{
  private volatile boolean flag = true;
  public void stopTask() {
    flag = false;
  }
  public MyThread(String name) {
    super(name);
  }
  @Override
  public void run() {
    synchronized (this) {
      int i = 0;
      while(flag) {
        try {
          Thread.sleep(100); // 休眠100ms
        } catch (InterruptedException ie) { 
          System.out.println(Thread.currentThread().getName() +" [ "+this.getState()+" ] catch InterruptedException."); 
          break;
        }
        i++;
        System.out.println(Thread.currentThread().getName()+" [ "+this.getState()+" ] loop " + i); 
      }
    }
    
  }
}

運(yùn)行結(jié)果

t1 [ NEW ] is new.
t1 [ RUNNABLE ] is started.
t1 [ RUNNABLE ] loop 1
t1 [ RUNNABLE ] loop 2
t1 [ RUNNABLE ] loop 3
t1 [ RUNNABLE ] is interrupted.
t1 [ TERMINATED ] is interrupted now.

四、interrupted() 和 isInterrupted()的區(qū)別

interrupted() 和 isInterrupted()都能夠用于檢測對象的“中斷標(biāo)記”。
區(qū)別是,interrupted() 除了返回中斷標(biāo)記之外,它還會(huì)清除中斷標(biāo)記(即將中斷標(biāo)記設(shè)為 false);而 isInterrupted() 僅僅返回中斷標(biāo)記。

以上就是深入分析JAVA 多線程--interrupt()和線程終止方式的詳細(xì)內(nèi)容,更多關(guān)于JAVA 多線程--interrupt()和線程終止的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

    MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解

    這篇文章主要介紹了MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 如何將Java枚舉名稱作為注解的屬性值實(shí)現(xiàn)詳解

    如何將Java枚舉名稱作為注解的屬性值實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了如何將Java枚舉名稱作為注解的屬性值實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 精致小巧的java相冊制作方法

    精致小巧的java相冊制作方法

    這篇文章主要為大家詳細(xì)介紹了精致小巧的java相冊制作方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Java實(shí)現(xiàn)單位換算功能

    Java實(shí)現(xiàn)單位換算功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)單位換算功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • IDEA中設(shè)置Tab健為4個(gè)空格的方法

    IDEA中設(shè)置Tab健為4個(gè)空格的方法

    這篇文章給大家介紹了代碼縮進(jìn)用空格還是Tab?(IDEA中設(shè)置Tab健為4個(gè)空格)的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-03-03
  • spring boot整合mybatis+mybatis-plus的示例代碼

    spring boot整合mybatis+mybatis-plus的示例代碼

    這篇文章主要介紹了spring boot整合mybatis+mybatis-plus的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • MyBatis+MyBatisPlus中遇到的一些坑及解決

    MyBatis+MyBatisPlus中遇到的一些坑及解決

    這篇文章主要介紹了MyBatis+MyBatisPlus中遇到的一些坑及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java文件與Base64之間的轉(zhuǎn)化方式

    Java文件與Base64之間的轉(zhuǎn)化方式

    這篇文章介紹了如何使用Java將文件(如圖片、視頻)轉(zhuǎn)換為Base64編碼,以及如何將Base64編碼轉(zhuǎn)換回文件,通過提供具體的工具類實(shí)現(xiàn),作者希望幫助讀者更好地理解和應(yīng)用這一過程
    2025-02-02
  • JAVA項(xiàng)目字典與緩存搭配使用方法解析

    JAVA項(xiàng)目字典與緩存搭配使用方法解析

    這篇文章主要介紹了JAVA項(xiàng)目字典與緩存搭配使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java web入門指南之在Idea上創(chuàng)建Java web項(xiàng)目

    Java web入門指南之在Idea上創(chuàng)建Java web項(xiàng)目

    好多書上的JavaWeb教程都是Eclipse以及MyEclipse,當(dāng)然這里不論IDE的好壞,下面這篇文章主要給大家介紹了關(guān)于Java web入門指南之在Idea上創(chuàng)建Java web項(xiàng)目的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06

最新評(píng)論

卫辉市| 卢氏县| 祥云县| 广汉市| 烟台市| 当雄县| 汪清县| 新巴尔虎左旗| 东乡县| 道真| 仙桃市| 洛川县| 张北县| 平陆县| 阜新| 泸西县| 白河县| 景宁| 柯坪县| 陆川县| 霞浦县| 苗栗市| 伊宁县| 岳阳市| 额济纳旗| 鄂温| 永州市| 车致| 泾川县| 资阳市| 南靖县| 牡丹江市| 朔州市| 田东县| 陵川县| 南阳市| 民和| 洛隆县| 新余市| 临洮县| 绥滨县|