本文系作者 chaoCode原創,轉載請私信並在文章開頭附帶作者和原文地址連結。

違者,作者保留追究權利。

前言

併發程式設計在我們日常開發中是時時刻刻都有在用的,只不過大部分的程式碼底層已經幫我們去做了一些併發程式設計的安全處理,但是還是有很多情況下需要我們自己去控制,所以我們需要去了解學習併發程式設計,那麼我們一步一步深入的開始學習。

認識java裡的執行緒

Java 程式天生就是多執行緒的

一個 Java 程式從 main()方法開始執行,然後按照既定的程式碼邏輯執行,看 似沒有其他執行緒參與,但實際上 Java 程式天生就是多執行緒程式,因為執行 main() 方法的是一個名稱為 main 的執行緒。

[6] Monitor Ctrl-Break //監控 Ctrl-Break 中斷訊號的

[5] Attach Listener //記憶體 dump,執行緒 dump,類資訊統計,獲取系統屬性等

[4] Signal Dispatcher // 分發處理髮送給 JVM 訊號的執行緒

[3] Finalizer // 呼叫物件 finalize 方法的執行緒

[2] Reference Handler//清除 Reference 的執行緒

[1] main //main 執行緒,使用者程式入口

Java執行緒的建立方式

Thread原始碼有說明Java執行緒建立方式,一共有兩種。

1.繼承Thread類

2.實現Runable介面

當然網上也有人說有第三種,通過實現Callable和Future介面來建立執行緒。

在Thread類原始碼中,給出了說明和執行緒建立方式示例:

Thread 才是 Java 裡對執行緒的唯一抽象,Runable、Callable、Future 只是對任務(業務邏輯) 的抽象。

因此,出現了多種執行緒建立方式的說法。

1.繼承Thread

  • [1] 定義Thread類的子類,並重寫該類的run()方法,run()方法被稱為執行緒執行體。
  • [2] 建立Thread子類的例項,即建立執行緒物件。
  • [3] 呼叫執行緒物件的start()方法啟動該執行緒。

2.實現Runnable介面

Thread提供一個帶引數的構造方法,我們通過實現Runnable介面再借用這個構造方法就可以獲取到根據我們自定義的任務的Thread物件

public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}

  • [1] 定義Runnable介面的實現類,並重寫該介面的run()方法。
  • [2] 建立Runnable實現類的例項,並以此例項作為Thread的target來建立Thread物件,該Thread物件才是真正的執行緒物件。
  • [3] 呼叫執行緒物件的start()方法來啟動該執行緒。

3.使用Callable和Future

實質也是使用Thread(Runnable target)構造方法,我們通過實現Callable介面實現一個帶返回值的任務,然後通過FutureTask類來包裝Callable物件,FutureTask這個類實現了RunnableFuture這個介面,但是RunnableFuture這個介面繼承了Runnable介面,所以就可以用這個構造方法就可以獲取到根據我們自定義的任務的Thread物件。





  • [1] 建立Callable介面的實現類,並實現call()方法,該call()方法作為執行緒執行體,且該call()方法有返回值。
  • [2] 建立Callable實現類的例項,使用FutureTask類來包裝Callable物件,該Future Task物件封裝了Callable物件的call()方法的返回值。
  • [3] 使用Future Task物件作為Thread物件的target建立執行緒物件。
  • [4] 呼叫執行緒物件的start()方法來啟動該執行緒。
  • [5] 呼叫Future Task物件的get()方法來獲得子執行緒執行結束後的返回值。

建立執行緒的三種方式對比

實現Runnable介面和實現Callable介面的方式基本相同,只是Callable接口裡定義的方法有返回值,可以宣告丟擲異常,大體上可以歸結為一大類。這種方式與繼承Thread方式之間的主要差別是採用實現Runnable,Callable介面建立多執行緒

1、執行緒類只是實現了Runnable介面或Callable介面,也可以繼續實現別的介面,還可以繼承其他類。

2、多個執行緒可以共享同一個Runnable物件,非常適合多個相同執行緒來處理同一份資源的情況(面向物件)。

3、如果要訪問當前執行緒,必須使用Thread.currentThread()方法,比較複雜。

採用繼承Thread類的方式建立執行緒:

1、因為執行緒類已經繼承了Thread類,所以不能再繼承其他父類。

2、如果要訪問當前執行緒,直接使用this即可獲得。

通過上面的分析我們發現建立執行緒的本質就如原始碼所寫那樣有兩種方式。一個是繼承Thread類,一種是實現Runnable介面。

通過對比我們發現,通過介面去建立執行緒的方式會讓我們程式碼有更大的容錯率,有更大的變通空間以及更加的靈活,同時也減少了程式之間的耦合度,畢竟六大原則中的依賴倒置原則的中心思想就是面向介面程式設計。所以推薦使用實現介面的方式來建立執行緒。

感謝諸君的觀看,文中如有紕漏,歡迎在評論區來交流。如果這篇文章幫助到了你,歡迎點贊關注。