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
分析
- 不同的線程去 ThreadLocal get 數據,得到的是和自己綁定的數據。
- 如果是子線程去 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