1. 程式人生 > >JAVA 執行緒中斷interrupt()

JAVA 執行緒中斷interrupt()

執行緒中斷有三種方法:

1、stop(),暴力中斷,會導致事物不完整,已被廢棄

2、flag標記法,用標記變數做迴圈條件,外部執行緒改變flag的值來達到中斷執行緒的目的

3、interrupt()和isInterrupted()配合使用,本質上和方法2一樣

重點看方法3如何實現

package com.nicovon;

public class ThreadTest extends Thread {

    public static void main(String[] args) throws InterruptedException {
        ThreadTest thread = new ThreadTest();
        System.out.println("Start.");
        thread.start();

        Thread.sleep(3000);
        System.out.println("interrupt thread");
        thread.interrupt();
        Thread.sleep(3000);
        System.out.println("stop thread");
    }

    @Override
    public void run(){
        while (!this.isInterrupted()) {
            System.out.println("Thread is running.");

            long time = System.currentTimeMillis();
            while (System.currentTimeMillis() - time < 1000);
        }
    }
}
執行結果:
Start.
Thread is running.
Thread is running.
Thread is running.
Thread is running.
interrupt thread
stop thread

Process finished with exit code 0


interrupte()方法會將中斷狀態status設定為true,注意這裡的中斷狀態並不在Thread類中,而是一個底層標誌,通過一些native方法來控制其值

初始時,status未設定,this.isInterrupted()返回false,一直迴圈,當主執行緒呼叫thread的interrupt()方法後,status被設定為true,迴圈終止

修改一下run()方法

public void run(){
        while (!this.isInterrupted()) {
            System.out.println("Thread is running.");

            try {
                Thread.sleep(1000);
                System.out.println("run sleep 1000");
            } catch (InterruptedException e) {
                System.out.println("Here get an InterruptedException");
            }
        }
    }

執行結果
Start.
Thread is running.
run sleep 1000
Thread is running.
run sleep 1000
Thread is running.
interrupt thread
Here get an InterruptedException
Thread is running.
run sleep 1000
Thread is running.
run sleep 1000
Thread is running.
stop thread
run sleep 1000
Thread is running.
run sleep 1000
Thread is running.

執行緒並沒有正常中斷,API中說

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

也就是說,線上程中使用sleep()等阻塞方法時呼叫interrupt()中斷操作時,中斷狀態不會置為true,反而會被清空,並且丟擲一個異常

如果在捕獲異常等catch塊中稍作修改

@Override
    public void run(){
        while (!this.isInterrupted()) {
            System.out.println("Thread is running.");

            try {
                Thread.sleep(1000);
                System.out.println("run sleep 1000");
            } catch (InterruptedException e) {
                System.out.println("Here get an InterruptedException");
                this.interrupt();
            }
        }
    }

執行結果
Start.
Thread is running.
run sleep 1000
Thread is running.
run sleep 1000
Thread is running.
interrupt thread
Here get an InterruptedException
stop thread

Process finished with exit code 0

如果知道中斷狀態status不在Thread類中,而是一個底層標誌就很好理解了

更普遍的做法是將while放到try catch塊裡面,間接跳出迴圈

注意:interrupte只能中斷可中斷的阻塞,可中斷的阻塞是指可以丟擲interruptexception的阻塞,像IO阻塞和syncrnized塊就屬於不可中斷阻塞