zoukankan      html  css  js  c++  java
  • ThreadLocal

      ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问, 通常是类中的 private static 字段,是对该字段初始值的一个拷贝,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联

      我们知道有时候一个对象的变量会被多个线程所访问,这时就会有线程安全问题,当然我们可以使用synchorinized 关键字来为此变量加锁,进行同步处理,从而限制只能有一个线程来使用此变量,但是加锁会大大影响程序执行效率,此外我们还可以使用ThreadLocal来解决对某一个变量的访问冲突问题。

      当使用ThreadLocal维护变量的时候 为每一个使用该变量的线程提供一个独立的变量副本,即每个线程内部都会有一个该变量,这样同时多个线程访问该变量并不会彼此相互影响,因此他们使用的都是自己从内存中拷贝过来的变量的副本, 这样就不存在线程安全问题,也不会影响程序的执行性能。

      但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。

    ThreadLocal 方法使用详解

    ThreadLocal 的几个方法: ThreadLocal 可以存储任何类型的变量对象, get返回的是一个Object对象,但是我们可以通过泛型来制定存储对象的类型。

    public T get() { } // 用来获取ThreadLocal在当前线程中保存的变量副本
    public void set(T value) { } //set()用来设置当前线程中变量的副本
    public void remove() { } //remove()用来移除当前线程中变量的副本
    protected T initialValue() { } //initialValue()是一个protected方法,一般是用来在使用时进行重写的

      Thread 在内部是通过ThreadLocalMap来维护ThreadLocal变量表, 在Thread类中有一个threadLocals 变量,是ThreadLocalMap类型的,它就是为每一个线程来存储自身的ThreadLocal变量的, ThreadLocalMap是ThreadLocal类的一个内部类,这个Map里面的最小的存储单位是一个Entry, 它使用ThreadLocal作为key, 变量作为 value,这是因为在每一个线程里面,可能存在着多个ThreadLocal变量

      初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。 
    然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找

    ThreadLocal 的应用场景

      最常见的ThreadLocal使用场景为 
      用来解决 数据库连接、Session管理等。

    二、原理

    线程共享变量缓存如下:

      Thread.ThreadLocalMap<ThreadLocalObject>;

    1、Thread: 当前线程,可以通过Thread.currentThread()获取。

    2、ThreadLocal:我们的static ThreadLocal变量。

    3、Object: 当前线程共享变量。

      我们调用ThreadLocal.get方法时,实际上是从当前线程中获取ThreadLocalMap<ThreadLocal,Object>,然后根据当前ThreadLocal获取当前线程共享变量Object。

      ThreadLocal.set,ThreadLocal.remove实际上是同样的道理。

    这种存储结构的好处:

    1、线程死去的时候,线程共享变量ThreadLocalMap则销毁。

    2、ThreadLocalMap<ThreadLocal,Object>键值对数量为ThreadLocal的数量,一般来说ThreadLocal数量很少,相比在ThreadLocal中用Map<Thread, Object>键值对存储线程共享变量(Thread数量一般来说比ThreadLocal数量多),性能提高很多。 

    关于ThreadLocalMap<ThreadLocalObject>弱引用问题:

      当线程没有结束,但是ThreadLocal已经被回收,则可能导致线程中存在ThreadLocalMap<null,Object>的键值对,造成内存泄露。(ThreadLocal被回收,ThreadLocal关联的线程共享变量还存在)。

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

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

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

  • 相关阅读:
    保持URL不变和数字验证
    centOS ftp key?
    本地环境测试二级域名
    linux 解决You don't have permission to access 问题
    php smarty section loop
    php header Cannot modify header information headers already sent by ... 解决办法
    linux部分命令
    Linux 里面的文件操作权限说明
    用IT网络和安全专业人士视角来裁剪云的定义
    SQL Server 2008 R2炫酷报表"智"作有方
  • 原文地址:https://www.cnblogs.com/guanghe/p/9222147.html
Copyright © 2011-2022 走看看