溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java高并發(fā)系列 - 第11天:線程中斷的幾種方式

發(fā)布時(shí)間:2020-06-10 21:54:50 來源:網(wǎng)絡(luò) 閱讀:209 作者:路人甲Java 欄目:編程語言

java高并發(fā)系列第11篇文章。

本文主要探討一下中斷線程的幾種方式。

通過一個(gè)變量控制線程中斷

代碼:

package com.itsoku.chat05;

import java.util.concurrent.TimeUnit;

/**
 * 微信公眾號(hào):javacode2018,獲取年薪50萬課程
 */
public class Demo1 {

    public volatile static boolean exit = false;

    public static class T extends Thread {
        @Override
        public void run() {
            while (true) {
                //循環(huán)處理業(yè)務(wù)
                if (exit) {
                    break;
                }
            }
        }
    }

    public static void setExit() {
        exit = true;
    }

    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.start();
        TimeUnit.SECONDS.sleep(3);
        setExit();
    }
}

代碼中啟動(dòng)了一個(gè)線程,線程的run方法中有個(gè)死循環(huán),內(nèi)部通過exit變量的值來控制是否退出。TimeUnit.SECONDS.sleep(3);讓主線程休眠3秒,此處為什么使用TimeUnit?TimeUnit使用更方便一些,能夠很清晰的控制休眠時(shí)間,底層還是轉(zhuǎn)換為Thread.sleep實(shí)現(xiàn)的。程序有個(gè)重點(diǎn):volatile關(guān)鍵字,exit變量必須通過這個(gè)修飾,如果把這個(gè)去掉,程序無法正常退出。volatile控制了變量在多線程中的可見性,關(guān)于volatile前面的文章中有介紹,此處就不再說了。

通過線程自帶的中斷標(biāo)志控制

示例代碼:

package com.itsoku.chat05;

import java.util.concurrent.TimeUnit;

/**
 * 微信公眾號(hào):javacode2018,獲取年薪50萬課程
 */
public class Demo2 {

    public static class T extends Thread {
        @Override
        public void run() {
            while (true) {
                //循環(huán)處理業(yè)務(wù)
                if (this.isInterrupted()) {
                    break;
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.start();
        TimeUnit.SECONDS.sleep(3);
        t.interrupt();
    }
}

運(yùn)行上面的程序,程序可以正常結(jié)束。線程內(nèi)部有個(gè)中斷標(biāo)志,當(dāng)調(diào)用線程的interrupt()實(shí)例方法之后,線程的中斷標(biāo)志會(huì)被置為true,可以通過線程的實(shí)例方法isInterrupted()獲取線程的中斷標(biāo)志。

線程阻塞狀態(tài)中如何中斷

示例代碼:

package com.itsoku.chat05;

import java.util.concurrent.TimeUnit;

/**
 * 微信公眾號(hào):javacode2018,獲取年薪50萬課程
 */
public class Demo3 {

    public static class T extends Thread {
        @Override
        public void run() {
            while (true) {
                //循環(huán)處理業(yè)務(wù)
                //下面模擬阻塞代碼
                try {
                    TimeUnit.SECONDS.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.start();
    }
}

運(yùn)行上面代碼,發(fā)現(xiàn)程序無法結(jié)束。

在此先補(bǔ)充幾點(diǎn)知識(shí):

  1. 調(diào)用線程的interrupt()實(shí)例方法,線程的中斷標(biāo)志會(huì)被置為true
  2. 當(dāng)線程處于阻塞狀態(tài)時(shí),調(diào)用線程的interrupt()實(shí)例方法,線程內(nèi)部會(huì)觸發(fā)InterruptedException異常,并且會(huì)清除線程內(nèi)部的中斷標(biāo)志(即將中斷標(biāo)志置為false)

那么上面代碼可以調(diào)用線程的interrupt()方法來引發(fā)InterruptedException異常,來中斷sleep方法導(dǎo)致的阻塞,調(diào)整一下代碼,如下:

package com.itsoku.chat05;

import java.util.concurrent.TimeUnit;

/**
 * 微信公眾號(hào):javacode2018,獲取年薪50萬課程
 */
public class Demo3 {

    public static class T extends Thread {
        @Override
        public void run() {
            while (true) {
                //循環(huán)處理業(yè)務(wù)
                //下面模擬阻塞代碼
                try {
                    TimeUnit.SECONDS.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    this.interrupt();
                }
                if (this.isInterrupted()) {
                    break;
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.start();
        TimeUnit.SECONDS.sleep(3);
        t.interrupt();
    }
}

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

java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at com.itsoku.chat05.Demo3$T.run(Demo3.java:17)

程序可以正常結(jié)束了,分析一下上面代碼,注意幾點(diǎn):

  1. main方法中調(diào)用了t.interrupt()方法,此時(shí)線程t內(nèi)部的中斷標(biāo)志會(huì)置為true
  2. 然后會(huì)觸發(fā)run()方法內(nèi)部的InterruptedException異常,所以運(yùn)行結(jié)果中有異常輸出,上面說了,當(dāng)觸發(fā)InterruptedException異常時(shí)候,線程內(nèi)部的中斷標(biāo)志又會(huì)被清除(變?yōu)閒alse),所以在catch中又調(diào)用了this.interrupt();一次,將中斷標(biāo)志置為false
  3. run()方法中通過this.isInterrupted()來獲取線程的中斷標(biāo)志,退出循環(huán)(break)

總結(jié)

  1. 當(dāng)一個(gè)線程處于被阻塞狀態(tài)或者試圖執(zhí)行一個(gè)阻塞操作時(shí),可以使用Thread.interrupt()方式中斷該線程,注意此時(shí)將會(huì)拋出一個(gè)InterruptedException的異常,同時(shí)中斷狀態(tài)將會(huì)被復(fù)位(由中斷狀態(tài)改為非中斷狀態(tài))
  2. 內(nèi)部有循環(huán)體,可以通過一個(gè)變量來作為一個(gè)信號(hào)控制線程是否中斷,注意變量需要volatile修飾
  3. 文中的幾種方式可以結(jié)合起來靈活使用控制線程的中斷

java高并發(fā)系列連載中,總計(jì)估計(jì)會(huì)有四五十篇文章,可以關(guān)注公眾號(hào):javacode2018,獲取最新文章。

java高并發(fā)系列 - 第11天:線程中斷的幾種方式

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI