Java 中的多線程

最近使用了不少關於多線程的東西,現在有些時間了,就把多線程的知識總結一下。歡迎拍磚。

首先是創建一個線程的方式,大概有四種:

第一,繼承 Thread 類並重寫其中的 run 方法,然後實例化該類並調用 start 方法啓動線程;

第二,實現 Runnable 接口並重寫其中的 run 方法,然後將該類的實例作爲 Thread 類的 target 創建一個 Thread 對象,調用 start 方法啓動線程;

第三,實現 Callable 接口並重寫其中的 call 方法,然後使用 FutureTask 包裝實現了 Callable 接口的類的對象,接下來將 FutureTask 類的實例作爲 Thread 類的 target 創建線程並調用 start 方法啓動線程;

第四,調用 Executors 的靜態方法創建一個線程池,然後使用返回的 ExecutorService 對象的 submit 方法將 Runnable 或 Callable 的實現類實例提交給線程池運行。

以上四種方式中,第一種方式是最基本的,第二種與第三種方式最終仍是創建了一個 Thread 類的對象,而最後一種方式通過線程池來實現性能的提高。

第一種方式由於所採取的是繼承 Thread 類,這也就導致了無法再繼承其他類,因此在靈活性上遜色於第二種方式,並且對於資源的共享而言,在子類中定義的實例屬性無法共享,安全固然安全,但也帶來了不便,甚至一定意義上失去了多線程的價值——共享數據。

第二種方式較常使用(^o^反正小菜我總是使用這種方式),重寫的 run 方法作爲線程執行體當調用 start 方法後開始處於就緒狀態。這種方式由於使用的是實現 Runnable 接口,故而彌補了 Java 的單重繼承,但最後仍是作爲 Thread 類的一個參數由 Thread 類的實例來執行線程,這也說明了在 Java 中是使用 Thread 類來代表線程,所有的線程對象都必須是 Thread 類或其子類的實例。

第三種方式的優勢是可以在線程執行完畢後得到一個返回值,並且能夠聲明拋出異常(是對於 call 方法而言),而重寫 run 方法則不允許如此 "亂來"。

最後一種實現方式非常方便,而且提高了性能,在對於線程的使用非常頻繁的地方運用。

注意點:

1,不能妄圖直接調用 run 方法或 call 方法而啓動一個線程,這樣做的效果與調用普通方法是一樣的,最終是在主線程執行方法,而不會創建一個子線程。

2,可以使用 Thread 類的實例方法 getName 來取得一個線程的名字,當沒有通過 setName 方法設置線程名字(或沒有在創建線程時傳入一個代表線程名字的字符串)時,默認情況下主線程名爲 "main" ,子線程依次命名爲 "Thread-0"、"Thread-1" 等,需要注意的是,在繼承自 Thread 類的子類中獲得當前線程的名字時可以直接使用 getName 方法,而在其他情形下要想獲得線程的名字,必須使用 "Thread.currentThread().getName()" 這種方式。

接下來是對於線程的控制,在 Java 中使用以下函數完成對線程的控制:

兩個 Thread 類中的靜態方法

① sleep  ② yield

一個實例方法

① join

當然還有其他方法,比如 stop、suspend、resume 等,但一般不使用。而以上三個方法中,第一個方法可以讓當前處於運行狀態的線程進入阻塞狀態,從而讓其他的線程得以執行,該方法的參數指定處於阻塞狀態的時間,時間過後線程會重新回到就緒狀態等待下一次執行;而 yield 方法只會讓當前線程處於就緒狀態,這也就是說當前線程仍可能被繼續執行,當程序中的其餘線程優先級低於當前線程時,調用該方法起不到預期效果,這時可以使用 setPriority 方法設置線程的優先級,也就是說,yield 方法只會給優先級等於或高於調用線程的線程以執行的機會。join 方法會使調用它的線程執行完之後再執行處於調用語句之後的代碼。

最後是線程安全問題。多線程使得資源的共享更爲方便,尤其是採用後面三種創建線程的方法,同時也使得線程的安全性得不到保障。多條線程對於共享數據的隨機修改會造成嚴重的程序邏輯錯誤,這是因爲一旦線程創建並啓動,各個線程之間的地位是完全相等的,不受創建它的線程影響。Java 中採用如下方式保證線程的安全性:

①同步代碼塊  ②同步方法  ③同步鎖

其中同步代碼塊可以使用任一對象作爲同步監視器,而同步方法默認使用當前對象作爲同步監視器,同步鎖則使得線程安全的操作更靈活。其實本質上這三者的思路都是相同的,都是使對於競爭資源的訪問遵循先加鎖才能訪問,使用結束就放鎖,以便其他線程獲得鎖進而訪問該資源。

當然多線程還有關於死鎖、通信等內容,說來慚愧,對此不熟悉,就不在各位關公面前耍大刀了。總之,多線程使得程序的結構更加理想,是程序中不可缺少的部分。

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