【多線程併發編程】九 線程Thread的停止

程序猿學社的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方法可以停止線程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章