ThreadLocal学习笔记

来源:互联网 发布:kingcms php 编辑:程序博客网 时间:2024/05/01 02:44

可参考《实战Java高并发程序设计》4.3

ThreadLocal是一个线程的局部变量,只有当前线程可以访问的数据。所以是线程安全的。

为每一个线程分配不同的对象,需要在应用层面保证。ThreadLocal只是起到了简单容器的作用。如果在应用上为每一个线程分配了相同的对象,ThreadLocal也不能保证线程安全。

/** *ThreadLocal简单使用 */public class TestTheadLocal {static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();public static class ParseDate implements Runnable {int i = 0;public ParseDate(int i) {this.i = i;}@Overridepublic void run() {if (tl.get() == null) {tl.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));}try {Date t = tl.get().parse("2016-06-29" + i % 60);System.out.println(i + ":" + t);} catch (ParseException e) {e.printStackTrace();}}}}

使用ThreadLocal为每一个线程都产生一个SimpleDateFormt对象实例。

实现原理(Jdk1.8的源码):其内部数据结构可以理解为一个HashMap,用户存储线程引用

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);    }

get

    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();    }


remove:及时回收对象,也可将tl=null

  /**         * Remove the entry for key.         */        private void remove(ThreadLocal<?> key) {            Entry[] tab = table;            int len = tab.length;            int i = key.threadLocalHashCode & (len-1);            for (Entry e = tab[i];                 e != null;                 e = tab[i = nextIndex(i, len)]) {                if (e.get() == key) {                    e.clear();                    expungeStaleEntry(i);                    return;                }            }        }

如果对象对于竞争的处理容易引起性能损失,应考虑使用ThreadLocal为每个线程分配单独的对象。典型案例就是多线程环境下产生随机数。


0 0
原创粉丝点击