1. 程式人生 > >【小家java】Java中主執行緒(父執行緒)與子執行緒的通訊和聯絡

【小家java】Java中主執行緒(父執行緒)與子執行緒的通訊和聯絡

相關閱讀

【小家java】java5新特性(簡述十大新特性) 重要一躍
【小家java】java6新特性(簡述十大新特性) 雞肋升級
【小家java】java7新特性(簡述八大新特性) 不溫不火
【小家java】java8新特性(簡述十大新特性) 飽受讚譽
【小家java】java9新特性(簡述十大新特性) 褒貶不一
【小家java】java10新特性(簡述十大新特性) 小步迭代
【小家java】java11新特性(簡述八大新特性) 首個重磅LTS版本


【小家java】Java中的執行緒池,你真的用對了嗎?(教你用正確的姿勢使用執行緒池)
小家Java】一次Java執行緒池誤用(newFixedThreadPool)引發的線上血案和總結


【小家java】BlockingQueue阻塞佇列詳解以及5大實現(ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue…)
【小家java】用 ThreadPoolExecutor/ThreadPoolTaskExecutor 執行緒池技術提高系統吞吐量(附帶執行緒池引數詳解和使用注意事項)


程序和執行緒(和協程)

通俗的講, 程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位(比如QQ是個程序、微信是個程序)

程序和執行緒的主要差別在於它們是不同的作業系統資源管理方式。

  1. 程序是具有一定獨立功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源分配和排程的一個獨立單位。每個程序都有自己的獨立記憶體空間,不同程序通過程序間通訊來通訊。由於程序比較重量,佔據獨立的記憶體,所以上下文程序間的切換開銷(棧、暫存器、虛擬記憶體、檔案控制代碼等)比較大,但相對比較穩定安全。
  2. 執行緒是程序的一個實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位.執行緒自己基本上不擁有系統資源,只擁有一點在執行中必不可少的資源(如程式計數器,一組暫存器和棧),但是它可與同屬一個程序的其他的執行緒共享程序所擁有的全部資源。執行緒間通訊主要通過共享記憶體,上下文切換很快,資源開銷較少,但相比程序不夠穩定容易丟失資料。
  3. **協程是一種使用者態的輕量級執行緒**,協程的排程完全由使用者控制。協程擁有自己的暫存器上下文和棧。協程排程切換時,將暫存器上下文和棧儲存到其他地方,在切回來的時候,恢復先前儲存的暫存器上下文和棧,直接操作棧則基本沒有核心切換的開銷,可以不加鎖的訪問全域性變數,所以上下文的切換非常快。

在Java中使用協程,一般會用到kilim( https://github.com/kilim/kilim )這個框架。因此本文不做討論

主執行緒與子執行緒之間的關係

1、最常見的情況,主執行緒中開啟了一個子執行緒,開啟之後,主執行緒與子執行緒互不影響各自的生命週期,即主執行緒結束,子執行緒還可以繼續執行;子執行緒結束,主執行緒也能繼續執行。
/**
 * @author [email protected]
 * @description
 * @date 2018-11-05 14:32
 */
public class Main {

    public static void main(String[] args) {
        System.out.println("主執行緒啟動。。。。");
        Thread thread = new Thread(new ChildThread());
        thread.start();
        System.out.println("主執行緒結束。。。。");
    }
}

class ChildThread implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("子執行緒啟動。。。。");
            Thread.sleep(5000);
            System.out.println("子執行緒結束。。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
輸出:
主執行緒啟動。。。。
主執行緒結束。。。。
子執行緒啟動。。。。
子執行緒結束。。。。
2、主執行緒開啟了子執行緒,但是主執行緒結束,子執行緒也隨之結束
thiredThread.setDaemon(true);

只需要把子執行緒設定為守護執行緒即可

3、主執行緒開啟了一個子執行緒,主執行緒必須要等子執行緒執行完之後,才能結束主執行緒
thread.join();

只需要把子執行緒自動後,join一下就行了

這裡使用了join()方法,讓主執行緒等待子執行緒結束,然後主執行緒繼續執行。這裡join()方法必須要在子執行緒啟動之後,再呼叫。

通訊

子執行緒與主執行緒的通訊,一般在Android中使用,因此本文也不作為重點進行討論

總結

程序是資源分配的基本單位,執行緒是cpu排程的基本單位。

但是上面通過呼叫JVM提供的介面,例如setDaemon與join改變了主執行緒與子執行緒的關係,這些應該是JVM介面程式碼做了處理干擾了執行緒的生命週期

對於cpu來說,其實不存在主執行緒和子執行緒之分,都是執行緒(JVM提供的API可能會改變執行緒的生命週期)。
守護執行緒與非守護執行緒本質上沒什麼區別,但是如果虛擬機器中存活的執行緒都是守護執行緒的時候,虛擬機器就會退出,只要虛擬機器中還有一個非守護執行緒,虛擬機器就不會退出。