JAVA線程-interrupt

JAVA線程-interrupt

中斷一個線程非常簡單,只需要在其他線程中對目標線程調用interrupt()方法,目標線程需要反覆檢測自身狀態是否是interrupted狀態,如果是,就立刻結束運行。

案例一:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread();
        t.start();
        Thread.sleep(1); // 暫停1毫秒
        t.interrupt(); // 中斷t線程
        t.join(); // 等待t線程結束
        System.out.println("end");
    }
}

class MyThread extends Thread {
    public void run() {
        int n = 0;
        while (! isInterrupted()) {
            n ++;
            System.out.println(n + " hello!");
        }
    }
}

Output:

....
33 hello!
34 hello!
35 hello!
end

上述案例很簡單,就是調用mythread的interrupt()方法,MyThread內部run中對線程中的中斷狀態進行判斷,並沒有真正意義上中斷線程。

案例二:

public class ThreadInterruptTest {
    public static void main(String[] args) {
        try {
            Thread t = new MyThread();
            t.start();
            Thread.sleep(1); // 暫停1毫秒
            System.out.println("before invoke interrupted");
            t.interrupt(); // 中斷t線程
            System.out.println("before main join");
            t.join(); // 等待t線程結束
            System.out.println("end");
        } catch (InterruptedException e) {
            System.out.println("main interrupted!");
        }
    }
}

class MyThread extends Thread {
    public void run() {
        int n = 0;
        try {
            while (!isInterrupted()) {
                n++;
                System.out.println(n + " hello!");
            }
            // mythread如果被調用了interrupt方法,並且mythread線程run方法中有拋出InterrutpedException的方法,就會拋出,沒有就不會拋出
            Thread.sleep(1);
        } catch (InterruptedException e) {
            System.out.println("mythread interrupted");
        }
    }
}

Output:

1 hello!
.....
51 hello!
before invoke interrupted
before main join
52 hello!
mythread interrupted
end

該案例就是案例一中,對MyThread中run方法新增了Thread.sleep方法調用,並catch了InterruptedException

此時發現MyThread中拋出了InterruptedException,但是案例一中並沒有拋出

所以對於處在sleep()方法阻塞下的線程,interrupt()方法會使線程拋出一個異常。

案例三:

public class ThreadInterruptTest2 {
    public static void main(String[] args) {
        try {
            Thread t = new MyThread2();
            t.start();
            Thread.sleep(1000);
            t.interrupt(); // 中斷t線程
            System.out.println("before main join");
            t.join(); // 等待t線程結束
            System.out.println("end");
        } catch (InterruptedException e) {
            System.out.println("main interrupted!");
        }
    }
}

class MyThread2 extends Thread {
    public void run() {
        Thread hello = new HelloThread();
        hello.start(); // 啓動hello線程
        try {
            hello.join(); // 等待hello線程結束
        } catch (InterruptedException e) {
            System.out.println("mythread interrupted!");
        }
        hello.interrupt();
    }
}

class HelloThread extends Thread {
    public void run() {
        int n = 0;
        while (!isInterrupted()) {
            n++;
            System.out.println(n + " hello!");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                System.out.println("hello interrupted");
                break;
            }
        }
    }
}

Output:

1 hello!
2 hello!
3 hello!
4 hello!
5 hello!
6 hello!
7 hello!
8 hello!
9 hello!
10 hello!
before main join
mythread interrupted!
hello interrupted
end

比案例二中更復雜了,嵌套線程調用

但是基本邏輯一樣,就是在調用線程中斷方法,線程的具體實現run中具有join調用,會拋出InterruptedException

所以對於處在sleep()、wait()和join()方法阻塞下的線程,interrupted方法會使線程拋出一個異常。

總結:

interrupt()不會去真正意義上的打斷一個正在運行的線程,而是修改這個線程的中斷狀態碼(interrupt status)。同時,對於處在sleep()、wait()和join()方法阻塞下的線程,該方法會使線程拋出一個異常。

與interrupt類似的方法

java.lang.Thread#isInterrupted()

判斷目標線程是否被中斷,不會清除中斷標記。

java.lang.Thread#interrupted

判斷目標線程是否被中斷,會清除中斷標記。

參考:

中斷線程

Java多線程--正確理解interrupt()、interrupted()和isInterrupted()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章