天天看點

教你在停車前為線程配個“保镖” | 帶你學《Java語言進階特性》之十三

上一篇:一文速解生産者-消費者模式問題 | 帶你學《Java語言進階特性》之十二

【本節目标】

通過閱讀本節内容,你将學會借助循環實作對線程的較為安全的停止操作,并學會建立守護線程,保證相關線程的平穩運作。

優雅的停止線程

在多線操作之中如果要啟動多線程使用的是Thread類中的start()方法,而如果對于多線程需要進行停止處理,Thread類原本提供有stop()方法,但是對于這些方法從JDK1.2版本就已經廢除了,而且一直到現在也不再建議使用,而除了stop()之外還有幾個方法也被禁用了:

  • 停止多線程:public final void stop();
  • 銷毀多線程:public void destroy();
  • 挂起線程:public final void suspend()、暫停執行;
  • 恢複挂起的線程執行:public final void resume();

之是以廢除掉這些方法,主要原因是因為這些方法可能導緻線程死鎖。是以,如果要想實作線程的停止需要通過一種柔和的方式來進行。

範例:實作線程柔和的停止

public class ThreadDemo {
    public static boolean flag = true;
    public static void main(String[] args) throws Exception {
        new Thread(() -> {
            long num = 0;
            while (flag) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在運作、num = " + num++);
            }
        }, "執行線程").start();
        Thread.sleep(200);     //運作200毫秒
        flag = false;      //停止線程
    }
}           
教你在停車前為線程配個“保镖” | 帶你學《Java語言進階特性》之十三

圖一 停止線程

萬一現在有其他線程去控制這個flag的内容,那麼這個時候對于線程的停止也不是說停就立刻停止的,而是會在執行中判斷flag的内容來完成。

守護線程

現在假設有一個人并且他有一個保镖,那麼這個保镖一定是在這個人活着時候進行守護,如果這個人死了,保镖就沒用了。是以在多線程中可以進行守護線程的定義,也就是說如果現在主線程的程式或者其他線程還在執行的時候,那麼守護線程将一直存在,并且運作在背景狀态。

在Thread類中提供有如下的守護線程的操作方法:

  • 設定為守護線程:public final void setDaemon(boolean on);
  • 判斷是否為守護線程:public final boolean isDaemon();

範例:使用守護線程

public class ThreadDemo {
    public static void main(String[] args) throws Exception {
        Thread userThread = new Thread(() -> {
            for (int x = 0 ; x < 10 ; x++) {
                try {
                    Thread.sleep(100) ;
                } catch (InterruptedException e) {
                    e.printStackTrace() ;
                }
                System.out.println(Thread.currentThread().getName() + "正在運作、x = " + x) ;
            }
        }, "使用者線程") ;         //完成核心業務
        Thread daemonThread = new Thread(() -> {
            for (int x = 0; x < Integer.MAX_VALUE ; x++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace() ;
                }
                System.out.println(Thread.currentThread().getName() + "正在運作、x = " + x) ;
            }
        }, "守護線程") ;     //完成核心業務
        daemonThread.setDaemon(true) ;        //設定為守護線程
        userThread.start() ;
        daemonThread.start() ;
    }
}           
教你在停車前為線程配個“保镖” | 帶你學《Java語言進階特性》之十三

圖二 守護線程

可以發現所有的守護線程都是圍繞在使用者線程的周圍,如果程式執行完畢了,守護線程也就消失了,在整個JVM中最大的守護線程就是GC線程。

程式執行中GC線程會一直存在,如果程式執行完畢,GC線程也将消失。

想學習更多的Java的課程嗎?從小白到大神,從入門到精通,更多精彩不容錯過!免費為您提供更多的學習資源。

本内容視訊來源于

阿裡雲大學 下一篇:另類的“同步”-volatile關鍵字 | 帶你學《Java語言進階特性》之十四 更多Java面向對象程式設計文章檢視此處