多线程并行与ThreadLocal存储

怎么让子线程也能拥有主线程ThreadLocal的值呢,很多童鞋第一反应是重写线程池的线程初始化方法,在初始化的的时候将ThreadLocal中保存的数据copy一份到子线程。这种方法是行不通的。线程池中的线程运行策略是判断当前队列中是否有任务,如果没有任务,则会在设定的时间后销毁;如果有任务,则会继续领下一个任务继续执行,而一般拒绝策略是CallerRunsPolicy。

为了解决线程池中变量传递,可以使用TransmittableThreadLocal的类,继承于InheritableThreadLocal。它通过包装返回Runnable的方式代理了run方法,在run之前copy装载线程变量,run之后清除线程变量,来实现此功能。为此需要修改runable接口。
com.alibaba.ttl.TtlRunnable#run 这个才是真正执行的run方法

 Object backup = replay(captured);
        try {
            runnable.run();
        } finally {
            restore(backup);
        }

TransmittableThreadLocal除了继承过来的线程Map,它还定义了一个名叫holder的InheritableThreadLocal静态变量,也就是说TransmittableThreadLocal有两套线程变量。
使用方法:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.5.0</version>
</dependency>

先调用TransmittableThreadLocal.set保存线程变量,除了正常保存外,还会保存到holder里。其实这么设置一下,当前线程的Map里就有两个Key-Value了,一个是TransmittableThreadLocal本身的,一个是holder的,并且holder真实的Value是一个WeakHashMap(也是弱引用),而且这个WeakHashMap会把TransmittableThreadLocal引用本身当做Key保存起来。外面传过进来的变量设置到当前执行任务的线程上去。run之后调用restoreBackup清除当前线程上被copied设置的变量并还原backup。

上一篇:清单文件,测试,打电话和发短信应用


下一篇:Web Speech API - 语音文本转换的Web解决方案