java多線程之創建線程與死鎖

線程創建篇

   java中的線程創建有多種方式,筆者(ymh)這裏分別根據線程執行完畢後是否有返回值討論線程創建的四種方式。

1、通過繼承Thread類重寫run方法(無返回值)

示例代碼:

2、通過實現Runnable接口(無返回值)

示例代碼:

  前兩種創建線程的方式是java初學者必須掌握的,這兩種方式可以說是創建線程最簡單的方式了,它們各有優缺點:

   第一種方式Thread類及其子類本身代表一個線程,重寫run方法來指定該線程具體執行的任務。優點是在需求不高的情況下編程比較簡單,但缺點是受限於java的單繼承機制,繼承了Thread類的子類不能再繼承其他類,這往往在某些情況下可能會帶來不便。

   第二種方式實現Runnable接口,則該類其實可以理解任務類,其實例就是線程要執行的某個具體的任務。這種方式的優點是多個線程可以共享一個任務對象,適合多個線程共同處理同一份資源的情況,較好地體現了面向對象的思想。缺點是編程相對複雜一些。

3、通過實現Callable接口(有返回值)

示例代碼:

  第三種方式可以獲取線程執行完畢後返回的結果。Callable 接口類似於Runnable接口,兩者都是爲那些其實例可能被另一個線程執行的類設計的。但是 Runnable 不會返回結果,並且無法拋出經過檢查的異常。

Callable實現類的實例可以使用FutureTask類(Future接口的實現類)封裝,然後通過FutureTask實例構造一個Thread線程,在線程執行完畢時而已使用FutureTask實例嘗試獲取線程的返回結果,即call方法的返回值。

4、通過Executor框架(有返回值)

示例代碼:

  第四種方式通過線程池執行任務,調用submit方法向線程池提交任務。Future 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。計算完成後只能使用 get 方法來獲取結果。

 

死鎖篇

   首先了解下什麼是死鎖:

  所謂的死鎖就是兩個即兩個以上的線程在執行的過程中,因爭奪資源而造成的一種相互等待的現象,若無外力作用,它們都將無法推進下去。死鎖是一種很嚴重的問題,可能會造成程序掛起而無法完成任務,編程時應合理的使用同步鎖機制來避免死鎖(其實應該是不要濫用同步鎖機制纔對)。

  死鎖產生的四個條件:

1、互斥條件:資源具有排他性,即一份資源同一時刻只能被一個線程佔用,直到該資源被釋放爲止。

2、請求與保持條件:當一個線程因請求被其他線程佔用的資源而阻塞時,對已佔用的資源保持不釋放。

3、不剝奪條件:當一份資源被某個線程佔用時,其他線程不能強行剝奪該資源。

4、循環等待條件:若干線程之間形成一種頭尾相接的循環等待資源的關係。

  一個簡單的死鎖案例:

  如何避免死鎖?

  避免死鎖最簡單的方法就是破壞循環等待條件,可以將系統中所有的資源設置標誌位、排序,規定所有線程申請資源必須按照一定的順序訪問。

例如有多個線程都需要訪問A、B、C三份資源,必須保證所有線程請求資源的順序都是一致的,例如先訪問A,再訪問B,最後訪問C。

  限定資源訪問的順序是一種簡單的避免死鎖的機制,但使用這種方式必須清楚每一個線程在其生命週期內都需要訪問什麼資源,這在實際編程中幾乎難以滿足。

還有一些其他的避免死鎖的機制,如加鎖時限、死鎖檢測等,筆者(ymh)在這裏不做討論,本文的初衷也僅是供初學者學習和拋磚引玉。轉載請註明出處!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章