ThreadLocal使用注意

ThreadLocal的出现是一种空间换时间的思想的运用,是为了多线程环境下单线程内变量共享的问题。它的原理就是每个线程通过ThreadLocal.ThreadLocalMap,保存当前线程中所有ThreadLocal变量引用的key和值。相当于每个线程有各自的变量副本,线程内共享这个变量数据,线程间互不影响。

ThreadLocal有它自己的使用场景,比如Spring中用它了解决Session、Connection等多线程并发访问问题,但不能它不能用来代替为了解决多线程安全问题的同步关键字,因为它实际上没有多线程间的变量共享,而线程安全问题是指多线程间变量共享,且共享变量可修改,进而可能会出现多线程并发修改共享变量的问题,这种需要通过同步手段解决。

ThreadLocal变量一般要声名成static类型,即当前线程中只有一个T类型变量的实例,线程内可共享该实例数据且不会出问题,如将其声名成非static,则一个线程内就存储多个T类型变量的实例,有点存储空间的浪费,一般很少有这样的应用场景。另外根据实际情况,ThreadLocal变量声名时也多加上private final关键词表明它时类内私有、引用不可修改。

在线程池环境下,由于线程是一直运行且复用的,使用ThreadLocal时会出现这个任务看到上个任务ThreadLocal变量值以及内存泄露等问题,解决方法就是在当前任务执行完后将ThreadLocal变量remove或设置为初始值,类似在Struts2 框架中Filter里的处理方法。

虽然ThreadLocal的get,set方法可以清除ThreadLocalMap中key为null的value,但是get,set方法在内存泄露后并不会必然调用,所以为了防止此类情况的出现,我们有两种手段。

1、使用完线程共享变量后,显示调用ThreadLocalMap.remove方法清除线程共享变量;

2、JDK建议ThreadLocal定义为private static,这样ThreadLocal的弱引用问题则不存在了。

最佳实践

最佳实践的方法参见google guava eventbus中对于ThreadLocal的使用

private final ThreadLocal<Boolean> dispatching;
    
    this.dispatching = new ThreadLocal() {
                protected Boolean initialValue() {
                    return Boolean.valueOf(false);
                }
            }
    if(!((Boolean)this.dispatching.get()).booleanValue()) {
                this.dispatching.set(Boolean.valueOf(true));

                Dispatcher.PerThreadQueuedDispatcher.Event nextEvent;
                try {
                    while((nextEvent = (Dispatcher.PerThreadQueuedDispatcher.Event)queueForThread.poll()) != null) {
                        while(nextEvent.subscribers.hasNext()) {
                            ((Subscriber)nextEvent.subscribers.next()).dispatchEvent(nextEvent.event);
                        }
                    }
                } finally {
                    this.dispatching.remove();
                    this.queue.remove();
                }
            }
复制代码
  • 采用匿名内部类赋初始值
  • 显式调用get()、set()
  • 在不用的时候显式地remove()掉
  • 对于显示的remove特别重要,因为这样可以避免entry不被GC的情况
  • 如果为了避免ThreadLocal被GC,可以加强ThreadLocal的引用,将其声明成private static
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值