程序猿學社的GitHub,歡迎Star
https://github.com/ITfqyd/cxyxs
本文已記錄到github,形成對應專題。
前言
最近,有一個網友,在某技術羣裏,提出一個問題,線程怎麼停止,有什麼好的方法,羣裏有不少人的回答,都是直接調用stop方法。我的回答是這樣的,各位可以幫我看看對不對。因爲停止線程也沒有我們想象中的那麼簡單。
方法一:stop方法
- 通過查看Thread類的源碼,我們可以發現stop方法上面有 @Deprecated註解,這個方法已經out。
- stop方法會導致代碼邏輯不完整,他收到停止命令後,會立即停止。
- stop方法會破壞原子邏輯。
過時
@Deprecated註解表示該方法是過時方法。
代碼邏輯沒有運行完,就退出
package com.cxyxs.thread.nine;
/**
* Description:驗證業務邏輯
* 轉發請註明來源 程序猿學社 - https://ithub.blog.csdn.net/
* Author: 程序猿學社
* Date: 2020/2/27 10:01
* Modified By:
*/
public class LogicIncomplete implements Runnable{
@Override
public void run() {
try {
System.out.println("正在運行代碼中");
Thread.sleep(1000);
System.out.println("關鍵代碼!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
LogicIncomplete logic = new LogicIncomplete();
Thread thread = new Thread(logic);
thread.start();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.stop();
}
}
- 子線程調用stop後,立馬就停止,因爲該進程內,沒有用戶線程,所以整個程序也自動退出了。
- 按照正常的退出邏輯,應該會輸出"關鍵代碼"這段話。例如,定時把15分鐘的圖片,10秒一張,合成一張圖片,流程是先把圖片打上水印,放到某個臨時文件夾,再合成視頻,再刪除臨時文件,如果中途調用stop方法,可能會導致本地有很多臨時文件。
- 這種方式因爲不安全,太粗暴,所以,不建議使用。
方法二:通過標識位,停止線程
package com.cxyxs.thread.nine;
/**
* Description:通過設置標誌位,停止線程
* 轉發請註明來源 程序猿學社 - https://ithub.blog.csdn.net/
* Author: 程序猿學社
* Date: 2020/2/27 14:32
* Modified By:
*/
public class FlagThread implements Runnable{
private boolean flag = true;
@Override
public void run() {
int count=1;
while (flag){
System.out.println("程序猿學社:"+count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
System.out.println("邏輯已跑完!");
}
}
public static void main(String[] args) throws InterruptedException {
FlagThread flagThread = new FlagThread();
Thread thread = new Thread(flagThread);
thread.start();
Thread.sleep(5000);
flagThread.flag = false;
}
}
- 主要邏輯,有兩個線程,main線程和我們自定義的線程,main線程延遲5秒後,直接通過標識位,把自定義的那個線程停止。
- 通過觀察結果,我們可以發現,通過這種方式停止,他會保證run方法裏面的業務邏輯都跑完。
- 使用該方面一定要給出終止條件,不然開銷成本不小。
- 如果這個線程,需要一直運行,最好,還是適當的讓出資源。
方法三:通過標識位+異常處理結束線程
package com.cxyxs.thread.nine;
/**
* Description:轉發請註明來源 程序猿學社 - https://ithub.blog.csdn.net/
* Author: 程序猿學社
* Date: 2020/2/27 14:55
* Modified By:
*/
public class InterruptThread implements Runnable{
private static boolean flag = true;
@Override
public void run() {
int count=1;
while (flag){
try {
System.out.println("程序猿學社:"+count);
Thread.sleep(1000);
} catch (InterruptedException e) {
this.flag = false;
e.printStackTrace();
}finally {
count++;
System.out.println("邏輯已跑完!");
}
}
}
public static void main(String[] args) throws InterruptedException {
InterruptThread interruptThread = new InterruptThread();
Thread thread = new Thread(interruptThread);
thread.start();
Thread.sleep(5000);
thread.interrupt();
}
}
- 通過測試,我們可以發現,通過異常+interrupt方式,我們可以順利的結束線程,也不會存在不安全的問題。
- interrupt是無法停止線程的,只是做個標記狀態,具體他的使用方法,我們後續再一步一步的分析他的源碼。
**總結:**創建線程,建議使用線程池的方式,裏面shutdown方法可以停止線程。