• ThreadLocal用法和实现原理


    背景:

           如果你定义了一个单实例的java bean,它有若干属性,但是有一个属性不是线程安全的,比如说HashMap。

           并且碰巧你并不需要在不同的线程中共享这个属性,也就是说这个属性不存在跨线程的意义。

           那么你不要sychronize这么复杂的东西,ThreadLocal将是你不错的选择。

     why:

          因为线程同步限制了并发访问,会带来很大的性能损失。

    误解:

          ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。

     正解:

           其实 ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易理解。

           从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

    举例来说:

    package com.xzc.util;
    
    import java.util.HashMap;
    
    /**
     * @Descrption
     * @Author xingzc
     * @Date 2018/11/9 10:18
     */
    public class TreadLocalTest {
        static ThreadLocal<HashMap> mapThreadLocal = new ThreadLocal<HashMap>() {
            @Override
            protected HashMap initialValue() {
                System.out.println(Thread.currentThread().getName() + "initialValue");
                return new HashMap();
            }
        };
    
        public void run() {
            Thread[] runs = new Thread[3];
            for (int i = 0; i < runs.length; i++) {
                runs[i] = new Thread(new T1(i));
            }
            for (int i = 0; i < runs.length; i++) {
                runs[i].start();
            }
        }
    
        public static class T1 implements Runnable {
            int id;
    
            public T1(int id0) {
                id = id0;
            }
    
            public void run() {
                System.out.println(Thread.currentThread().getName() + ":start");
                HashMap map = mapThreadLocal.get();
                for (int i = 0; i < 10; i++) {
                    map.put(i, i + id * 100);
                    try {
                        Thread.sleep(100);
                    } catch (Exception ex) {
                    }
                }
                System.out.println(Thread.currentThread().getName() + ':' + map);
            }
        }
    
        /**
         * Main
         *
         * @param args
         */
        public static void main(String[] args) {
            TreadLocalTest test = new TreadLocalTest();
            test.run();
        }
    
    }
    

      

    输出解释;

    Thread-0:start
    Thread-2:start
    Thread-1:start
    Thread-2initialValue
    Thread-0initialValue
    Thread-1initialValue
    Thread-0:{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}
    Thread-2:{0=200, 1=201, 2=202, 3=203, 4=204, 5=205, 6=206, 7=207, 8=208, 9=209}
    Thread-1:{0=100, 1=101, 2=102, 3=103, 4=104, 5=105, 6=106, 7=107, 8=108, 9=109}
    

      结论:

    1) mapThreadLocal虽然是个静态变量,但是initialValue被调用了三次,通过debug发现,initialValue是从mapThreadLocal.get处发起的;

    2) ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本 ,变量是线程安全的共享对象

    3) ThreadLocal确实只有一个变量,但是它内部包含一个ThreadLocalMap,针对每个thread保留一个entry,如果对应的thread不存在则会调用initialValue;

    源码解析:

          Theadlocal 代码片段;

    /**
         * 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) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue();
        }
    
    

     

    /**
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    

      

     

    在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。 

    参考

     @ ThreadLocal和线程同步机制对比

  • 相关阅读:
    亚像素显示详解
    一文看懂显示关键材料之彩色滤光片(Color Filter)
    Android Camera2 Opengles2.0 实时滤镜(冷暖色/放大镜/模糊/美颜)
    Android Camera2 预览,拍照,人脸检测并实时展现
    Camera2点击对焦实现2
    关于Android Camera2 API 的自动对焦的坑
    Camera2点击对焦实现
    Android 新老两代 Camera API 大起底
    Android Camera2 参数调节关键字翻译集合,常用关键字解析
    MediaCodec在Android视频硬解码组件的应用
  • 原文地址:https://www.cnblogs.com/xingzc/p/5752401.html
Copyright © 2020-2023  润新知