<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 閱讀(4765) 評論(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熱點博客

    好友博客

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 又粗又长又爽又长黄免费视频| 国产一区二区三区免费观在线| 可以免费观看的一级毛片| 污视频网站免费观看| 亚洲精品午夜无码电影网| 亚洲免费观看在线视频| 精品一区二区三区无码免费直播| 国产亚洲AV手机在线观看| 精品无码免费专区毛片| 免费看内射乌克兰女| 亚洲视频网站在线观看| 老司机永久免费网站在线观看| 中国黄色免费网站| 亚洲欧洲日韩极速播放| 亚洲欧洲自拍拍偷午夜色无码| 最近的中文字幕大全免费版| a毛片在线免费观看| 亚洲国产成人久久精品软件| 国产AV无码专区亚洲AV男同| 好吊妞在线新免费视频| a级毛片毛片免费观看久潮| 亚洲人成网站18禁止| 久久精品视频亚洲| avtt亚洲天堂| 亚洲免费网站观看视频| 最新国产乱人伦偷精品免费网站| 亚洲AV无码专区亚洲AV桃| 亚洲精品线在线观看| 国产精品亚洲玖玖玖在线观看| 国产1024精品视频专区免费| 成人性生交大片免费看好| 亚洲av色香蕉一区二区三区 | 国产精品成人亚洲| 亚洲无人区视频大全| 亚洲人成网亚洲欧洲无码久久| 午夜视频免费成人| 91精品成人免费国产片| 国产一精品一AV一免费| 一区二区免费国产在线观看| 久久亚洲精品无码gv| 亚洲高清视频在线|