1. 程式人生 > >百度Android面試題之如何停止一個執行緒

百度Android面試題之如何停止一個執行緒

前段時間去面試了百度android職位,雖然沒有通過,但是發現了很多自己的不足,回來痛定思痛,決定將所有的面試題整理到CSDN上,查漏補缺。

問:如何停止一個執行緒?

由於平時不怎麼寫多執行緒,所以直接說了個interrupt()顯然是不對的。那麼接下來我們探討一下java中如何停止一個執行緒。

Thread.stop()

該方法已經不推薦使用,它不能保證安全的退出執行緒,這裡不討論。

interrupt()方式

我們先來學習下執行緒的interrupt()、interrupted()、isInterrupted()方法的區別

interrupt():作用是中斷本執行緒,是例項方法

這裡的中斷執行緒,並非真正的把執行緒終止,而是將“中斷標記”設定為true。

在本執行緒內,中斷自身是允許的:將“中斷標記”設定成true

其他執行緒中呼叫本執行緒的interrupt(),會通過checkAccess()檢查許可權,可能丟擲SecurityException()異常。

    若本執行緒當前是阻塞狀態,呼叫interrupt()後,它的“中斷執行緒”狀態被清除,並收到InterruptException異常

    若本執行緒當前是執行狀態,則會將中斷標記設定為true。

interrupted()方法:判斷當前執行緒是否處於中斷狀態,是Thread的靜態方法,如下:

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

isInterrupted()方法:判斷呼叫執行緒是否處於中斷狀態,是例項方法

例如:

public static void main(String[] args){
  Thread thread = new Thread(()->{}); //定義一個執行緒,虛擬碼沒有具體實現
  thread.isInterrupted();//判斷thread是否處於中斷狀態,而不是主執行緒是否處於中斷狀態
  Thread.isInterrupted(); //判斷主執行緒是否處於中斷狀態
}

那麼,接下來,我們探究如何停止一個執行緒

使用呼叫需要被中斷的執行緒的interrupt()方法,在需要被中斷的執行緒run()方法中使用isInterrupted()判斷,並catch InterruptException異常來carry需要被中斷的執行緒是阻塞的情況。程式碼如下:

public class StopThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        NeedStopThread thread = new NeedStopThread();
        thread.start();
        //主執行緒sleep,此時子執行緒在執行
        Thread.sleep(300);
        //在主執行緒中呼叫thread.interrupt();終端該執行緒
        thread.interrupt();
        Thread.sleep(300);
        System.out.println("is interrupted:"+thread.isInterrupted());

    }
}

class NeedStopThread extends Thread {
    @Override
    public void run() {
        try {
            //這裡可以直接寫成while(!isInterrupted)為了列印這樣寫
            while (true) {
                //記錄當前中斷情況
                boolean isInterrupted = isInterrupted();
                System.out.println("isInterrupted:"+isInterrupted);
                if (!isInterrupted) {
                    //處理業務
                    //Thread.sleep(5); 1處
                }else{
                    break;
                }
            }
        } catch (Exception e) {
            System.out.println("catch e"+e.toString());
            //carry執行緒阻塞時,外部呼叫interrupt()丟擲的interruptedException
        }

    }
}

結果:

isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:true
is interrupted:false

若放開註釋1處,結果如下:

isInterrupted:false
isInterrupted:false
isInterrupted:false
isInterrupted:false
catch ejava.lang.InterruptedException: sleep interrupted
is interrupted:false
因為當外部(主執行緒)呼叫thread.interrupt()時,thread正在執行,而執行的內容是sleep(阻塞)當前執行緒。所以會丟擲異常。這也符合我們上述所說:當需要被中斷的執行緒是阻塞狀態。外部呼叫thread.interrupt(),會丟擲InterruptedException異常