1. 程式人生 > 其它 >Java執行緒使用技巧學習(一)

Java執行緒使用技巧學習(一)

Java執行緒使用技巧學習(一)

Java執行緒有哪些不太為人所知的技巧與用法?   蘿蔔白菜各有所愛。像我就喜歡Java。學無止境,這也是我喜歡它的一個原因。日常工作中你所用到的工具,通常都有些你從來沒有了解過的東西,比方說某個方法或者是一些有趣的用法。比如說執行緒。沒錯,就是執行緒。或者確切說是Thread這個類。當我們在構建高可擴充套件性系統的時候,通常會面臨各種各樣的併發程式設計的問題,不過我們現在所要講的可能會略有不同。   從本文中你將會看到執行緒提供的一些不太常用的方法及技術。不管你是初學者還是高階使用者或者是Java專家,希望都能看一下哪些是你已經知道的,而哪些是剛瞭解的。如果你認為關於執行緒還有什麼值得分享給大家的,希望能在下面積極回覆。那我們就先開始吧。   初學者   1.執行緒名   程式中的每個執行緒都有一個名字,建立執行緒的時候會給它分配一個簡單的Java字串來作為執行緒名。預設的名字是”Thread-0″, “Thread-1″, “Thread-2″等等。現在有趣的事情來了——Thread提供了兩種方式來設定執行緒名:

  • 執行緒建構函式,下面是最簡單的一個實現:

class SuchThread extends Thread {

    Public void run() {
        System.out.println ("Hi Mom! " + getName());
    }

}

SuchThread wow = new SuchThread("much-name");
  • 執行緒名setter方法:
wow.setName(“Just another thread name”);

  沒錯,執行緒名是可變的。因此我們可以在執行時修改它的名字,而不用在初始化的時候就指定好。name欄位其實就是一個簡單的字串物件。也就是說它能達到2³¹-1個字元那麼長(Integer.MAX_VALUE)。這足夠用了。注意這個名字並不是一個唯一性的標識,因此不同的執行緒也可以擁有同樣的執行緒名。還有一點就是,不要把null用作執行緒名,否則會丟擲異常(當然了,”null”還是可以的)。 使用執行緒名來除錯問題   既然可以設定執行緒名,那麼如果遵循一定的命名規則的話,出了問題的時候排查起來就能更容易一些。“Thread-6″這樣的名字看起來就太沒心沒肺了,肯定有比它更好的名字。在處理使用者請求的時候,可以將事務ID追加到執行緒名後面,這樣能顯著減少你排查問題的時間。

“pool-1-thread-1″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 
nid=0x6d03 in Object.wait() [0x000000013ebcc000]

  “pool-1-thread-1″,這也太嚴肅了吧。我們來看下這是什麼情況,給它起一個好點的名字:

Thread.currentThread().setName(Context + TID + Params + current Time, ...);
  

現在我們再來執行下jstack,情況便豁然開朗了:


”Queue Processing Thread, MessageID: AB5CAD, type: 
AnalyzeGraph, queue: ACTIVE_PROD, Transaction_ID: 5678956,
 Start Time: 30/12/2014 17:37″ #17 prio=5 os_prio=31 tid=0x00007f9d620c9800 
nid=0x6d03 in Object.wait() [0x000000013ebcc000]

如果我們能知道執行緒在做什麼,這樣當它出問題的時候,至少可以拿到事務ID來開始排查。你可以回溯這個問題,復現它,然後定位問題並搞定它。如果你想知道jstack有什麼給力的用法,可以看下這篇文章。   2. 執行緒優先順序   執行緒還有一個有意思的屬性就是它的優先順序。執行緒的優先順序介於1 (MINPRIORITY)到10 (MAXPRIORITY)之間,主執行緒預設是5(NORM_PRIORITY)。每個新執行緒都預設繼承父執行緒的優先順序,因此如果你沒有設定過的話,所有執行緒的優先順序都是5。這個是通常被忽視的屬性,我們可以通過getPriority()與setPriority()方法來獲取及修改它的值。執行緒的建構函式裡是沒有這個功能的。 什麼地方會用到優先順序?   當然並不是所有的執行緒都是平等的,有的執行緒需要立即引起CPU的重視,而有些執行緒則只是後臺任務而已。優先順序就是用來把這些告訴給作業系統的執行緒排程器的。在Takipi中,這是我們開發的一錯誤跟蹤及排查的工具,負責處理使用者異常的執行緒的優先順序是MAX_PRIORITY,而那些只是在上報新的部署情況的執行緒,它們的優先順序就要低一些。你可能會覺得優先順序高的執行緒從JVM的執行緒排程器那得到的時間會多一些。但其實並都是這樣的。   在作業系統層面,每一個新執行緒都會對應一個本地執行緒,你所設定的Java執行緒的優先順序會被轉化成本地執行緒的優先順序,這個在各個平臺上是不一樣的。在Linux上,你可以開啟“-XX:+UseThreadPriorities”選項來啟用這項功能。正如前面所說的,執行緒優先順序只是你所提供的一個建議。和Linux本地的優先順序相比,Java執行緒的優先順序並不能覆蓋全所有的級別(Linux共有1到99個優先順序,執行緒的優先順序在是-20到20之間)。最大的好處就是你所設定的優先順序能在每個執行緒獲得的CPU時間上有所體現,不過完全依賴於執行緒優先順序的做法是不推薦的。