1. 程式人生 > >【多執行緒】——停止執行緒的三種方式

【多執行緒】——停止執行緒的三種方式

前提

    停止執行緒是在多執行緒開發時非常重要的方式,掌握執行緒的停止可以對執行緒的停止進行有效的處理。停止執行緒在Java中不像break那樣乾脆,而需要一些技巧性。

停止執行緒的方式有三種,分別展示一下

方式一

使用退出標識,使得執行緒正常退出,即當run方法完成後程序終止。

public void run() {
    while(flag){
        //do something
    }
}

利用識別符號flag判定執行緒是否繼續執行。

方式二

使用stop強行中斷執行緒(此方法為作廢過期方法),不推薦使用,暴力終止,可能使一些清理性的工作得不到完成。還可能對鎖定的內容進行解鎖,容易造成資料不同步的問題。

方式三

使用interrupt方法中斷執行緒。

在Thread.java類裡提供了兩種方法判斷執行緒是否為停止的。

this.interrupted():測試當前執行緒是否已經中斷(靜態方法)。如果連續呼叫該方法,則第二次呼叫將返回false。在api文件中說明interrupted()方法具有清除狀態的功能。執行後具有將狀態標識清除為false的功能。

this.isInterrupted():測試執行緒是否已經中斷,但是不能清除狀態標識。

執行緒停止——拋異常法

public class MyThread4 extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 50000; i++) {
            if (this.isInterrupted()) {
                System.out.println( "執行緒已經結束,我要退出" );
                break;
            }
            System.out.println( "i=" + (i + 1) );
        }
        System.out.println( "我是for下面的語句,我被執行說明執行緒沒有真正結束" );
    }
}
   public static void main(String[] args) {
        try {
            MyThread4 myThread4 = new MyThread4();
            myThread4.start();
            Thread.sleep( 20);
            myThread4.interrupt();
        } catch (InterruptedException e) {
            System.out.println( "main catch" );
            e.printStackTrace();
        }
    }

根據列印結果發現for後面的內容依舊會執行,為了解決這種問題,可以採用拋異常的方式,或return的方式終止執行緒。一般推薦拋異常的方式,這樣才能使得執行緒停止得以擴散。

public class MyThread4 extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 50000; i++) {
                if (this.isInterrupted()) {
                    System.out.println( "執行緒已經結束,我要退出" );
//                    return;
                    throw new InterruptedException();
                }
                System.out.println( "i=" + (i + 1) );
            }
            System.out.println( "我是for下面的語句,我被執行說明執行緒沒有真正結束" );
        } catch (InterruptedException e) {
            System.out.println( "進入MyThread.java類中run方法的catch異常了" );
            e.printStackTrace();
        }
    }
}

在沉睡中停止

先sleep,後interrupt

  @Override
    public void run() {
        super.run();
        try {
            System.out.println( "begin run" );
            Thread.sleep( 500 );
            System.out.println( "begin end" );
        } catch (InterruptedException e) {
            System.out.println("在沉睡中終止");
            e.printStackTrace();
        }
    }
 public static void main(String[] args) {
        try {
            MyThread5 thread5 = new MyThread5();
            thread5.start();
            Thread.sleep( 20 );
            thread5.interrupt();
        } catch (InterruptedException e) {
            System.out.println( "main catch" );
            e.printStackTrace();
        }
    }

從列印結果看,sleep狀態下停止某一個執行緒,會進入catch語句,並清除狀態值,變成false

先interrupt後sleep

  try {
            for (int i = 0; i < 10000; i++) {
                System.out.println( "i="  +(i + 1) );
            }
            System.out.println( "run begin" );
            Thread.sleep( 200 );
            System.out.println( "run end" );
        } catch (InterruptedException e) {
            System.out.println( "先停止,後sleep" );
            e.printStackTrace();
        }
 public static void main(String[] args) {
            MyThread5 thread5 = new MyThread5();
            thread5.start();
            thread5.interrupt();
    }

任務執行完成後,才丟擲異常!

總結

    很基礎的內容,多加積累!