結合interrupt state來理解interrupt

[TOC]

Thread類的interrupt方法倒是見過好幾次,但是一直不知道他的具體是干什么的,今天查了以下api和core java大概解決了自己的疑惑。(順便吐槽一下core java的翻譯,問題實在不少)

一、關于interrupt state

There is boolean flag in every thread that indicating the interrupt state,When the interrupt method is called on a thread, the interrupted status of the thread is set. --core java
每個線程都有一個布爾變量表示線程的中斷狀態,當線程調用interrupt后,線程的中斷狀態會設置.
另外,中斷狀態 可以通過線程的isInterrupted()返回值來判定,true表示設置為中斷狀態,false表示非中斷狀態;
The interrupt method can be used to request termination of a thread.   --core java
interrupt方法可以請求中斷一個線程(也就是說只是請求中斷,并不能直接中斷).

以下代碼驗證了上述結論,可以看到程序的輸出會出現這種情況:首先為false,interrupt以后,變為true,但是程序依舊會輸出0到9;

private void simpleInterrupt() {
    Thread t = new Thread(){
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(i);
            }
        }
    };

    t.start();
    System.out.println("before interrupt:" + t.isInterrupted());
    t.interrupt();
    System.out.println("after interrupt:" + t.isInterrupted());
}

由此可見,interrupt并不像它的中文意思中斷一樣能中斷線程,但是改變了isInterrupted方法的返回值,這個還是可以作為run方法的循環結束的條件,從而中斷線程,代碼如下:

private void simpleInterruptAffect() {
    Thread t = new Thread(){
        @Override
        public void run() {
            for (int i = 0; i < 100 && !isInterrupted(); i++) {
                System.out.println(i);
            }
        }
    };

    t.start();
    try {
        Thread.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    t.interrupt();
}

多運行幾遍,發現i沒到99就結束了。

二、sleep、wait等方法和interrupt的聯系

1. 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.  --doc
當線程由于sleep或者wait等方法阻塞時,如果調用了interrupt方法,就會拋出一個異常(補充:core java上說是由于系統無法檢測處于阻塞狀態線程的interrupt state),并且清除掉線程的interrupt status(使得isInterrupted方法返回false),用代碼驗證一下:

 private void interruptSleep() {
   Thread t1 = new Thread() {
           @Override
           public void run() {
               try {
                Thread.sleep(1000);
                } catch (InterruptedException e) {
                System.out.println("interrupt status in catch:" + isInterrupted());
                }
            }
    };
    t1.start();
    System.out.println("interrupt status before interrupt:" + t1.isInterrupted());
    t1.interrupt();
    System.out.println("interrupt status after interrupt:" + t1.isInterrupted());

}

一般會依次輸出
interrupt status before interrupt:false
interrupt status after interrupt:true
interrupt status in catch:false
2. 線程不能睡眠的原因
If you call the sleep method when the interrupted status is set, it doesn’t sleep. Instead, it
clears the status and throws an InterruptedException.
如果線程睡眠前線程它的isInterrupted返回true,線程就不會睡眠,相反,線程的會清除掉interrupt status并且拋出一個異常。同樣用代碼驗證一下。

volatile boolean flag = false;
private void interruptThenSleep() {

    Thread t = new Thread(){
        @Override
        public void run() {
            while(!flag){}
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                System.out.println("interrupt status in catch:" + isInterrupted());
            }
        }
    };

    t.start();
    t.interrupt();
    System.out.println("interrupt status after interrupt:" + t.isInterrupted());
    flag = true;

}

t線程不會休眠10s
并且輸出:
interrupt status after interrupt:true
interrupt status in catch:false
到這里可也以得出結論:只要線程的isInterrupted()返回true,Thread.sleep()都會拋出異常,并且清除線程的中斷狀態。

3.關于interrupted
Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method.  --doc

檢測當前線程是否處于中斷狀態,調用后中斷狀態會重置(狀態變量變為false)

同樣驗證一下

package com.basic;

/**
 * Created by liouville on 3/25/16.
 */
public class CompareInterrupt {

    volatile static  boolean flag = true;
    public static void main(String[] args) {

        MyThread t = new MyThread();
        t.start();

        System.out.println("主線程:" + t.isInterrupted());
        t.interrupt();

        flag = false;
    }

    private static class MyThread extends Thread{
        @Override
        public void run() {
            super.run();
            System.out.println("run...");

            while (flag){yield();}
            System.out.println(isInterrupted());
            System.out.println(interrupted());
            System.out.println(isInterrupted());
        }
    }
}

一般輸出:
主線程:false
run...
true
true
false

三、interrupt interrupted isInterrupted

現在可以更清晰的看到三者之間的區別。
interrupt用來請求中斷線程,但是只是設置一下線程的中斷狀態的標記變量,并不會直接中斷線程。
isInterrupted用來判斷
調用該方法的線程
是否處于中斷狀態,處于中斷狀態返回true,否則false;,不會影響這個中斷狀態標記變量的值。
interrupted是一個靜態方法,也是用來檢測當前線程是否處于中斷狀態,處于中斷狀態返回true,否則false,但是它會重置中斷狀態的標記變量為false.**

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容