首頁 >Java >java教程 >ThreadLocal是什麼? ThreadLocal的原理分析

ThreadLocal是什麼? ThreadLocal的原理分析

不言
不言轉載
2018-10-11 16:37:3810897瀏覽

這篇文章帶給大家的內容是關於ThreadLocal是什麼? ThreadLocal的原理分析,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

1、 ThreadLocal是什麼

ThreadLocal提供執行緒局部變數。這些變數與普通的變數不同之處在於,每個存取這種變數的執行緒(透過它的get或set方法)都有自己的、獨立初始化的變數副本。

ThreadLocal實例通常是希望將狀態關聯到一個執行緒的類別的私人靜態欄位(例如,user ID 或 Transaction ID 等等)。

(畫外音:這段話表達了三個意思

1、ThreadLocal是一種變數類型,我們稱之為「線程局部變數」。

2、每個執行緒存取這種變數的時候都會建立該變數的副本,這個變數副本為線程私有。

3、ThreadLocal類型的變數一般用private static加以修飾。)

例如,下面的例子中這個類別為每個執行緒產生唯一標識。一個執行緒的id是它第一次呼叫ThreadId.get()方法指定的。

package com.cjs.example;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadId {
    private static final AtomicInteger nextId = new AtomicInteger(0);
    private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            return nextId.getAndIncrement();
        }
    };
    public static int get() {
        return threadId.get();
    }
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getId());
                }
            }).start();
        }
    }
}

2.  ThreadLocal主要動作

/**
 * 返回当前线程对ThreadLocal变量的“初始值”
 * 这个方法将在线程第一次访问变量(通过调用get方法)时被调用,如果之前已经调用过了就不会再调了
 *
 * @return the initial value for this thread-local
 */
protected T initialValue() {
    return null;
}

/**
 * 设置当前线程的ThreadLocal变量的副本为指定的值
 *
 * @param value the value to be stored in the current thread&#39;s 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变量副本的值
 *
 * @return the current thread&#39;s value of this thread-local
 */
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

/**
 * 删除当前线程的ThreadLocal变量副本的值
 */
public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

3.  閱讀原始碼

3.1.  set方法

可以看到,ThreadLocalMap底層是一個數組,數組中元素類型是Entry類型

set操作是向當前線程的ThreadLocal.ThreadLocalMap類型的成員變數threadLocals中設定值,key是this,value是我們指定的值

注意,這裡傳的this代表的是那個ThreadLocal類型的變數(或者說叫做對象)

也就是說,每個執行緒都維護了一個ThreadLocal.ThreadLocalMap類型的對象,而set操作其實就是以ThreadLocal變數為key,以我們指定的值為value,最後將這個鍵值對封裝成Entry物件放到該執行緒的ThreadLocal.ThreadLocalMap物件中。每個ThreadLocal變數在該執行緒中都是ThreadLocal.ThreadLocalMap物件中的一個Entry。既然每個ThreadLocal變數都對應ThreadLocal.ThreadLocalMap中的一個元素,那麼就可以對這些元素進行讀寫刪除操作。

3.2.  get方法

get()方法是從目前執行緒的ThreadLocal.ThreadLocalMap物件中取出對應的ThreadLocal變量所對應的值

同理,remove()方法就是清除這個值

用圖形表示的話,大概是這樣的:

或是這樣的:

4.  ThreadLocal使用場景

在執行緒生命週期內傳值

最後,一切都歸功於ThreadLocalMap

以上是ThreadLocal是什麼? ThreadLocal的原理分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除