Thread详解12:InheritableThreadLocal的使用
2016-03-31 02:28
357 查看
ThreadLocal的用法可以参考上一篇博文: http://blog.csdn.net/cds86333774/article/details/51020819,InheritableThreadLocal是ThreadLocal的子类。该类扩展了 ThreadLocal,为子线程提供从父线程那里继承的值:在创建子线程时,子线程会接收所有可继承的线程局部变量的初始值,以获得父线程所具有的值。通常,子线程的值与父线程的值是一致的;但是,通过重写这个类中的 childValue 方法,子线程的值可以作为父线程值的一个任意函数。当必须将变量(如用户 ID 和 事务 ID)中维护的每线程属性(per-thread-attribute)自动传送给创建的所有子线程时,应尽可能地采用可继承的线程局部变量,而不是采用普通的线程局部变量。
如果是子线程去 InheritableThreadLocal get 数据,得到的是和父线程一样的数据,也就是子线程继承了父线程在 InheritableThreadLocal 里面的数据,这个数据变成了“家族数据”
原来这个方法返回的是子线程在第一次get的时候的初始值,如果不重写,默认就是返回父线程的值,所以出现上面示例代码的输出。在形式上和ThreadLocal的initialValue类似。
下面我重写childValue,使子线程的初始值为父线程的值+1:
输出
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
相关文章推荐
- C#实现窗体与子线程的交互的方法
- C#在子线程中更新窗口部件的写法
- android开发教程之子线程中更新界面
- Android中子线程和UI线程通信详解
- 子线程更新UI(非Handle)
- 实现死锁的两种方式以及ReentrantLock的额外功能(未完待续)
- android之AsncTask异步任务使用
- UI线程、子线程 以及子线程间的通信
- 最近学习qt,一些细节备忘
- iOS 图片流的上传
- 【安卓】使用Handler完成子线程更新ui
- 子线程获取数据,主线程更新UI
- Android系统上可以在子线程修改UI吗
- MFC子线程向主线程SendMessage或者直接操作UI时可能导致子线程的退出异常
- Android两个子线程之间通信
- 关于Qt在子线程中使用QMessageBox的折衷方法
- 子线程开启RunLoop
- Thread详解11:ThreadLocal的使用
- APUE:线程:主线程与子线程的关系
- Android Looper详解