跨线程使用ThreadLocal

最近围观@田麦大牛的代码,看到ThreadLocal还能这么玩,故此记录一下

ThreadLocal概念:http://blog.csdn.net/qjyong/article/details/2158097

可以明显看到ThreadLocal中的值是和线程本身绑定的,那么如果我在A线程中使用了ThreadLocal,set了一个变量,然后在B线程如何取出来呢。

往ThreadLocal中set变量时,可以debug这个类,发现类中除了一串hashCode外什么都没有,那么这个值究竟放在哪里呢?

threadLocalHashCode = -387276957

 看一下ThreadLocal的set方法

 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的变量全部是存储在Thread的

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null; 

  中,由于ThreadLocalMap是不可见的,所以只能通过反射的方式去调用。

到此为止,ThreadLocal就已经与线程并非完全相关了,你大可以对ThreadLocalMap进行copy,在采用事件回调等机制不同线程的情况下也可以run的很愉快了。完整代码如下:

public abstract class Task implements Runnable {
    Object threadLocal;
    public Task(Object threadLocalMap){
        this.threadLocal =threadLocalMap;
    }
    public final void run(){
        BeanUtils.forceSetProperties(Thread.currentThread(), threadLocal, "threadLocals");
        realRun();
    }

    protected abstract void realRun();
}
 

例子:

public class ThreadLocalTest {
    private static final ThreadLocal<String> tl = new ThreadLocal<String>();

    static class MyTask extends Task{
        public MyTask(Object threadLocal){
            super(threadLocal);
        }
        @Override
        public void realRun() {
            System.out.println("I'm Thread:"+Thread.currentThread().getName()+", value is:"+tl.get());
          }
    }

    public static void main(String[] args) {
        tl.set("hello world");
        Object threadLocals = BeanUtils.forceGetProperties(Thread.currentThread(),"threadLocals");
        Executors.newSingleThreadExecutor().submit(new MyTask(threadLocals));
        System.out.println("I'm Thread:"+Thread.currentThread().getName()+", value is:"+tl.get());
    }

}

BeanUtils:

public static Object forceGetProperties(Object object, String fieldName){
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            if (!field.isAccessible()){
                field.setAccessible(true);
            }
            return field.get(object);
        } catch (Exception e) {
            //ignore
            return null;
        }
    }

    public static void forceSetProperties(Object target,Object arg, String fieldName){
        try {
            Field field = target.getClass().getDeclaredField(fieldName);
            if (!field.isAccessible()){
                field.setAccessible(true);
            }
            field.set(target,arg);
        } catch (Exception e) {
            //ignore
        }
    } 

 

运行结果:

I'm Thread:main, value is:hello world

I'm Thread:pool-1-thread-1, value is:hello world

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值