关于 ThreadLocal

                            关于 ThreadLocal

关于ThreadLocal

  java提供了java.lang.ThreadLocal,主要是用于解决多线程情况下变量安全的问题。

  当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。


ThreadLocal提供了4个接口:

  1. void set(Object value) 设置当前局部变量的值

  2. Object get()该方法返回当前线程所对应的线程局部变量。

  3. public void remove()将当前线程局部变量的值删除。线程结束后,会自动回收内存。

  4. protected Object initialValue()返回该线程局部变量的初始值


使用场景

  1. 当我们需要维护一个变量,并且这个变量需要在多线程情况下安全

  2. 不想使用synchronized复杂的同步机制的

ThreadLocal使用例子

  看一下下面的一个简单的例子,多线程情况下,更新变量。

<span style="font-family:FangSong_GB2312;font-size:18px;">public class Test2 {

    public static ThreadLocal<Integer> tl = new ThreadLocal<Integer>();

    /**
     * 入口函数
     * @param args
     */
    public static void main(String[] args) throws Exception {

        for (int i = 0; i < 4; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    for (int i = 0; i < 4; i++) {
                        Test2.tl.set(i);
                        System.out.println("Thread:" + Thread.currentThread().getId()
                                + " ThreadLocal值:" + Test2.tl.get());
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e) {
                        }
                    }
                }
            }).start();
        }
    }
}
</span>

  结果:

ThreadLocal源码实现

  set方法源码。可以看到set方法的时候,会去取当前的线程信息。然后放入ThreadLocalMap中。ThreadLocalMap是ThreadLocal类的一个静态内部类,它实现了键值对的设置和获取(对比Map对象来理解),每个线程中都有一个独立的ThreadLocalMap副本,它所存储的值,只能被当前线程读取和修改。ThreadLocal类通过操作每一个线程特有的ThreadLocalMap副本,从而实现了变量访问在不同线程中的隔离。

<span style="font-family:FangSong_GB2312;font-size:18px;">    /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }</span>

  get方法源码。
<span style="font-family:FangSong_GB2312;font-size:18px;">    /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }</span>

  静态内部类和非静态内部类区别:

  1. 内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。

  2. 非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。

  3. 一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。


  ThreadLocalMap就是一个静态内部类,Thread每个线程上都会有一个ThreadLocalMap,所以能实现线程安全。

 

             转自:http://blog.csdn.net/initphp/article/details/8259391




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值