前段時間去面試了百度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異常