<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 262,  comments - 221,  trackbacks - 0

    關于ThreadLocal的用法,之前一直不太清楚,直到最近看了網上一篇文章《深入研究java.lang.ThreadLocal類》,再結合SUN的API,才對這個類有了一定的了解。

    ThreadLocal的核心思想很簡單:為每個獨立的線程提供一個變量的副本。

    我們知道在多線程的情況下,幾個線程同時訪問同一變量的情況很常見,Java提供的synchronized關鍵字使用了“同步鎖”的機制來阻止線程的競爭訪問,即“以時間換空間”。

    ThreadLocal則使用了“拷貝副本”的方式,人人有份,你用你的,我用我的,大家互不影響,是“以空間換時間”。每個線程修改變量時,實際上修改的是變量的副本,不怕影響到其它線程。

    ThreadLocal的一個最常見應用是為每個線程分配一個唯一的ID,例如線程ID,事務ID,一般保存在ThreadLocal中的變量都是很少需要修改的。

    為了加深對ThreadLocal的理解,下面我使用一個例子來演示ThreadLocal如何隔離線程間的變量訪問和修改:

    【1】SerialNum類

    package example.thread.threadLocal;

    public class SerialNum {

        
    private static int nextSerialNum = 1;

        @SuppressWarnings(
    "unchecked")
        
    private static ThreadLocal serialNum = new ThreadLocal() {
            
    protected synchronized Object initialValue() {
                return new Integer(nextSerialNum++);      

            }                                                           
        };

        
    public static int get() {
            
    return ((Integer) (serialNum.get())).intValue();
        }
        
        @SuppressWarnings(
    "unchecked")
        
    public static void set(Integer newSerial){
            serialNum.set(newSerial);
        }
    }

    【2】GetSerialNumThread
    package example.thread.threadLocal;

    public class GetSerialNumThread implements Runnable {

        
    public static void main(String args[]) {

            GetSerialNumThread serialNumGetter 
    = new GetSerialNumThread();
            Thread t1 
    = new Thread(serialNumGetter, "Thread A");
            Thread t2 
    = new Thread(serialNumGetter, "Thread B");
            t1.start();
            
    try {
                t1.join();
            } 
    catch (InterruptedException e) {
                e.printStackTrace();
            }    
            t2.start();            
        }

        
    public void run() {
            
    int mySerialNum = getSerialNum();
            System.out.println("線程 " + Thread.currentThread().getName()
                    
    + " 獲取到的序列號是" + mySerialNum);
            System.out.println(
    "線程 " + Thread.currentThread().getName()
                    
    + " 修改了序列號為" + (mySerialNum * 3));
            setSerialNum(mySerialNum * 3);

            System.out.println(
    "線程 " + Thread.currentThread().getName()
                    
    + " 再次獲得的序列號是" + getSerialNum());
        }

        
    private int getSerialNum() {
            
    return SerialNum.get();
        }

        
    private void setSerialNum(int newSerialNum) {
            SerialNum.set(
    new Integer(newSerialNum));
        }
    }

    運行的結果如下:
    線程 Thread A 獲取到的序列號是1
    線程 Thread A 修改了序列號為3
    線程 Thread A 再次獲得的序列號是3
    線程 Thread B 獲取到的序列號是2
    線程 Thread B 修改了序列號為6
    線程 Thread B 再次獲得的序列號是6

    可見第一個線程在調用SerialNum.set(int)方法修改static變量時,其實修改的是它自己的副本,而不是修改本地變量,第二個線程在初始化的時候拿到的序列號是2而不是7。

    為什么會這樣呢?明明serialNum是靜態變量啊?其實我們只需要看看ThreadLocal的內部構造就知道了:

    A. ThreadLocal的get()方法:
     /**
         * Returns the value in the current thread's copy of this thread-local
         * variable.  Creates and initializes the copy if this is the first time
         * the thread has called this method.
         *
         * 
    @return the current thread's value of this thread-local
         
    */
        
    public T get() {
            Thread t 
    = Thread.currentThread();
            ThreadLocalMap map 
    = getMap(t);
            
    if (map != null)
                
    return (T)map.get(this);

            
    // Maps are constructed lazily.  if the map for this thread
            
    // doesn't exist, create it, with this ThreadLocal and its
            
    // initial value as its only entry.
            T value = initialValue();
            createMap(t, value);
            
    return value;
        }

    B. ThreadLocal的set()方法:
    /**
         * Sets the current thread's copy of this thread-local variable
         * to the specified value.  Many applications will have no need for
         * this functionality, relying solely on the {
    @link #initialValue}
         * method to set the values of thread-locals.
         *
         * 
    @param value the value to be stored in the current threads' copy of
         *        this thread-local.
         
    */
        
    public void set(T value) {
            Thread t 
    = Thread.currentThread();
            ThreadLocalMap map 
    = getMap(t);
            
    if (map != null)
                map.set(
    this, value);
            
    else
                createMap(t, value);
        }

    可以看到ThreadLocal在內部維護了一個Map,將變量的值和線程綁定起來,get/set方法都是對該線程對應的value進行操作,所以不會影響到其它線程。

    -------------------------------------------------------------
    生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
    posted on 2008-09-05 17:10 Paul Lin 閱讀(4752) 評論(1)  編輯  收藏 所屬分類: J2SE


    FeedBack:
    # re: 【原】Java 多線程 之 ThreadLocal
    2008-09-05 19:03 | 銀河使者
    在MyEclipse中開發基于hibernate的程序時,自動生成的Session工廠就用了ThreadLocal,以保證每一個線程只有一個Session。

    實際上,ThreadLocal的基本原理就是利用線程的id作為Map的key,將一個對象作為Map的value, 以保證一個線程只有一個key-value對。由于每一個線程有一個獨立的對象,而且每個線程的對象必須獨立,也就是說不能有其他的線程訪問當前線程的對象,這樣對于每個線程來說,是順序執行的,也就不可能發生象臟數據這樣的事情了。  回復  更多評論
      
    <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    BlogJava熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 青草久久精品亚洲综合专区| 亚洲乱码中文字幕小综合| 先锋影音资源片午夜在线观看视频免费播放| 亚洲国产精品久久久久秋霞影院| 国产精品免费_区二区三区观看 | 国产一区二区三区在线观看免费| xxxxwww免费| 国产精品久久久久免费a∨ | 亚洲一区二区三区成人网站| 亚洲精品**中文毛片| 无码久久精品国产亚洲Av影片| 亚洲乱码中文字幕久久孕妇黑人| 亚洲天堂中文字幕在线| 亚洲人成人无码网www国产| 亚洲А∨精品天堂在线| 亚洲男人天堂2020| 亚洲一区二区三区影院| 亚洲人成人一区二区三区| 亚洲精品无码久久久久| 久久亚洲AV午夜福利精品一区 | 最近最新高清免费中文字幕| 国产成人免费高清激情视频| 国产自产拍精品视频免费看| 亚洲人成无码久久电影网站| 亚洲精品乱码久久久久久久久久久久 | 成年网站免费视频A在线双飞| 欧美日韩国产免费一区二区三区| 免费的一级片网站| 狠狠色伊人亚洲综合成人| 亚洲婷婷天堂在线综合| 污污免费在线观看| 最近免费视频中文字幕大全| 日韩毛片无码永久免费看| 国产午夜亚洲精品国产成人小说| 久久精品a亚洲国产v高清不卡| 亚洲国产乱码最新视频| 成人毛片100免费观看| 性感美女视频在线观看免费精品| 亚洲人成网77777亚洲色| 亚洲精品无码av片| 日日麻批免费40分钟无码|