Thread詳解12:InheritableThreadLocal的使用

ThreadLocal的用法可以參考上一篇博文: http://blog.csdn.net/cds86333774/article/details/51020819,InheritableThreadLocal是ThreadLocal的子類。該類擴展了 ThreadLocal,爲子線程提供從父線程那裏繼承的值:在創建子線程時,子線程會接收所有可繼承的線程局部變量的初始值,以獲得父線程所具有的值。通常,子線程的值與父線程的值是一致的;但是,通過重寫這個類中的 childValue 方法,子線程的值可以作爲父線程值的一個任意函數。當必須將變量(如用戶 ID 和 事務 ID)中維護的每線程屬性(per-thread-attribute)自動傳送給創建的所有子線程時,應儘可能地採用可繼承的線程局部變量,而不是採用普通的線程局部變量。

1 子線程

如果線程A創建了線程B,那麼B就是A的子線程。


2 示例代碼

用法和ThreadLocal幾乎一樣,但是效果不一樣。

ThreadLocalTest.java

package threadLocalTest;

import java.util.Random;

public class ThreadLocalTest {
    private static ThreadLocal<Integer> familyFortunes = new ThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            Random random = new Random();
            return random.nextInt(1000);
        }
    };

    public static int get() {
        return familyFortunes.get();
    }

    public static void set(int value) {
        familyFortunes.set(value);
    }

}

InheritableThreadLocalTest.java

package threadLocalTest;

import java.util.Random;

public class InheritableThreadLocalTest {
    private static InheritableThreadLocal<Integer> familyFortunes = new InheritableThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            Random random = new Random();
            return random.nextInt(1000);
        }
    };

    public static int get() {
        return familyFortunes.get();
    }

    public static void set(int value) {
        familyFortunes.set(value);
    }

}

Thread2.java

package threadLocalTest;

public class Thread2 extends Thread {

    public Thread2(String name) {
        super(name);
    }

    @Override
    public void run() {
        super.run();
        System.out.printf("%s 從 ThreadLocal 取數據:%d\n", Thread.currentThread().getName(), ThreadLocalTest.get());
        System.out.printf("%s 從 InheritableThreadLocal 取數據:%d\n", Thread.currentThread().getName(),
                InheritableThreadLocalTest.get());
    }

    public static void main(String[] args) {
        System.out.printf("%s 從 ThreadLocal 取數據:%d\n", Thread.currentThread().getName(), ThreadLocalTest.get());
        System.out.printf("%s 從 InheritableThreadLocal 取數據:%d\n", Thread.currentThread().getName(),
                InheritableThreadLocalTest.get());
        Thread2 t1 = new Thread2("Child1");
        t1.start();
    }
}

輸出

main 從 ThreadLocal 取數據:444
main 從 InheritableThreadLocal 取數據:401
Child1 從 ThreadLocal 取數據:513
Child1 從 InheritableThreadLocal 取數據:401

分析

  1. 不同的線程去 ThreadLocal get 數據,得到的是和自己綁定的數據。
  2. 如果是子線程去 InheritableThreadLocal get 數據,得到的是和父線程一樣的數據,也就是子線程繼承了父線程在 InheritableThreadLocal 裏面的數據,這個數據變成了“家族數據”

3 childValue

看完childValue方法的說明,我還是不知道它怎麼用,我們來看看源碼:

    /**
     * Computes the child's initial value for this inheritable thread-local
     * variable as a function of the parent's value at the time the child
     * thread is created.  This method is called from within the parent
     * thread before the child is started.
     * <p>
     * This method merely returns its input argument, and should be overridden
     * if a different behavior is desired.
     *
     * @param parentValue the parent thread's value
     * @return the child thread's initial value
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }

原來這個方法返回的是子線程在第一次get的時候的初始值,如果不重寫,默認就是返回父線程的值,所以出現上面示例代碼的輸出。在形式上和ThreadLocal的initialValue類似。

下面我重寫childValue,使子線程的初始值爲父線程的值+1:

package threadLocalTest;

import java.util.Random;

public class InheritableThreadLocalTest {
    private static InheritableThreadLocal<Integer> familyFortunes = new InheritableThreadLocal<Integer>() {
        @Override
        protected Integer initialValue() {
            Random random = new Random();
            return random.nextInt(1000);
        }

        @Override
        protected Integer childValue(Integer parentValue) {
            return parentValue+1;
        }


    };

    public static int get() {
        return familyFortunes.get();
    }

    public static void set(int value) {
        familyFortunes.set(value);
    }



}

輸出

main 從 ThreadLocal 取數據:506
main 從 InheritableThreadLocal 取數據:570
Child1 從 ThreadLocal 取數據:953
Child1 從 InheritableThreadLocal 取數據:571
發佈了66 篇原創文章 · 獲贊 15 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章