深刻理解Java中中止線程

一.中止線程會帶來什麼?安全

對於單線程中,中止單線程就是直接使用關鍵字return或者break,可是在中止多線程時是讓線程在完成任務前去開啓另一條線程,必須放棄當前任務,而這個過程是不可預測,因此必須去作好防備。性能優化

二.認識中止線程的幾個方法多線程

 2.1三個被棄用的方法架構

 stop()、suspend()、resume()。併發

 stop()方法被棄用的緣由:不管線程執行到了什麼位置,一旦被stop就會被立刻強制中斷,而且釋放線程全部持有鎖對象,根本就沒有安全性。分佈式

 suspend()和resume()這一對爛兄爛弟,由於只有其餘線程調用resume這個方法時他纔會釋放suspend這個方法的鎖,這樣就極易形成死鎖。ide

 2.2三個名字差很少的方法微服務

 interrupt()中斷線程、interrupted()判斷當前線程是否中止、isInterrupted()判斷線程是否中止。高併發

 首先來介紹一下其中兩個名字最相近的:interrupted()、isInterrupted()方法,這兩個方法是用來測試線程是否被中斷的。源碼分析

 來看一下原碼:

isInterrupted():

public boolean isInterrupted() {
        return isInterrupted(false);
    }

 

 interrupted():

public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

能夠明顯看出interrupted()方法是靜態的,而isInterrupted()是非靜態的,但都是返回線程是否被中斷。

下面咱們來作一個測試,代碼以下:

 

public class Is_Interrupt extends Thread{
        @Override
        public void run(){
            for(int i=0;i<1000;i++){
                System.out.println("當前i的值爲:"+i);
            }
        }
        public static void main(String[] args) {
            Is_Interrupt is_interrupt=new Is_Interrupt();
            is_interrupt.start();
            is_interrupt.interrupt();//中斷線程
            System.out.println("線程是否已經暫停?"+is_interrupt.interrupted());
        }
    }

 

 

 輸出結果爲:

 

 

 

 

發現線程沒有中止。

可是這裏面還有一個線程就是main線程,而interrupted()返回的就是當前線程的中斷狀態,那麼執行這個方法的就是main線程,而main線程此時固然沒有中斷。

咱們將interrupted()方法改成isInterrupted()試試效果,代碼以下:

 

public class Is_Interrupt extends Thread{
        @Override
        public void run(){
            for(int i=0;i<1000;i++){
                System.out.println("當前i的值爲:"+i);
            }
        }
        public static void main(String[] args) {
            Is_Interrupt is_interrupt=new Is_Interrupt();
            is_interrupt.start();
            is_interrupt.interrupt();//中斷線程
            System.out.println("線程是否已經暫停?"+is_interrupt.isInterrupted());
        }
    }

 

 

結果以下:

 

 

 

 

說明線程是已經中止了的,只不過咱們使用錯了一個方法而已判斷成了main線程的狀態。

總結:isInterrupted方法是返回調用對象的中斷狀態,而靜態方法interrupted是返回當前線程的中斷狀態。

既然瞭解了這個誤區之後咱們再來看看下面的代碼:

 

public class InterruptText extends Thread{
    public static void main(String[] args) {
        System.out.println("main線程啓動!");
        System.out.println( Thread.interrupted());//判斷當前線程是否中斷
        System.out.println(currentThread().isInterrupted());//經過currentThread().isInterrupted()一樣也能夠達到相同的目的,在單線程中
    }
}

 

 

輸出:

 

 

 

這個是沒有問題的。

那麼咱們屢次調用這個interrupted方法呢?

 

public class InterruptText extends Thread{
    public static void main(String[] args) {
        System.out.println("main線程啓動!");
        currentThread().interrupt();//中斷main線程
        System.out.println( Thread.interrupted());//判斷當前main線程是否中斷
        System.out.println( Thread.interrupted());//再一次判斷當main前線程是否中斷
    }
}

 

 

 結果:

 

 

 

按照常理應該兩次返回ture,可是爲何變成了第二次變成了false了呢?

其實interrupted就是在清除狀態,你兩次調用固然會將true變成flase可是他仍是中斷狀態,可是isInterrupted是不清除的。

interrupt()方法:中斷線程

三.中止線程

3.1經過異常來暫停線程

 首先來看一段代碼:

 

public class InterruptText extends Thread{
    @Override
    public void run(){
        try {
            for (int i = 0; i < 100000; i++) {
                if (currentThread().isInterrupted()) {//若是線程中斷
                    throw new InterruptedException();//拋出異常
                } else {
                    System.out.println(i);
                }
            }
            System.out.println("線程沒有終止");
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws Exception {
        InterruptText interruptText=new InterruptText();
        interruptText.start();
        Thread.sleep(100);
        interruptText.interrupt();
    }
}

 

 

 結果:

 

 

 

 

異常中止方法的策略就是:在遇到中斷時,拋出異常,撲捉異常。

3.2在睡眠中中斷線程

 代碼以下:

 

public class InterruptText2 extends Thread {
    @Override
    public void run(){
        try {
            Thread.sleep(10000);//線程睡眠
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        InterruptText2 interruptText2=new InterruptText2();
        interruptText2.start();//開啓線程,可是線程處於睡眠狀態
        interruptText2.interrupt();//在睡眠狀態中斷線程
        
    }
}

 

 

 結果爲:

 

 

 

 

3.3線程讓步

 方法:yield(),當前線程放棄全部的資源,去執行其餘的任務。可是放棄資源的時間不能夠預判的。

3.4守護線程

 守護線程的定義:守護線程是一種特殊的線程,區別於非守護線程,當程序中不存在非守護線程時,守護線程退出,程序退出。

設置守護線程:setDaemon(),參數爲ture則該線程爲守護線程。

在此我向你們推薦一個架構學習交流羣。交流學習羣號874811168 裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構等這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多

相關文章
相關標籤/搜索