1. 程式人生 > >java多執行緒之建立執行緒與死鎖

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)在這裡不做討論,本文的初衷也僅是供初學者學習和拋磚引玉。轉載請註明出處!