标签:nes 脏数据 map ice 回收 原理 java并发编程 静态 shutdown
线程本地存储是一个自动化机制,可以为使用相同变量的每个不同的线程都创建不同的存储。简单来说,就是对于某个变量,针对不同的线程存储不同的值。
实例:
import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @Description * @Author KToTo * @Date 2019/3/18 22:22 **/ public class ThreadLoaclVariableHolder { //创建一个全局的ThreadLocal对象 private static ThreadLocal<Integer> value = new ThreadLocal<Integer>(){ private Random random = new Random(47); //初始化方法,此处的Random相当于共享变量,为了使演示效果明显, //故将该初始化方法同步 protected synchronized Integer initialValue() { return random.nextInt(1000); } }; //提供公有的递增和获取方法 public static void increment() { value.set(value.get() + 1); } public static int get() { return value.get(); } public static void main(String[] args) throws InterruptedException { ExecutorService pool = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { pool.execute(new Accessor(i)); } //与Thread.sleep(long mils)方法功能一致 TimeUnit.SECONDS.sleep(3); //立即关闭线程池,不熟悉的读者可以自行百度shutdown和shutdownNow的区别 pool.shutdownNow(); } } class Accessor implements Runnable { private final int id; public Accessor(int id) { this.id = id; } @Override public void run() { //响应中断 while (!Thread.currentThread().isInterrupted()) { ThreadLoaclVariableHolder.increment(); System.out.println(this); //对于多核处理器,此方法可以省略 Thread.yield(); } } @Override public String toString() { return "Accessor{" + "id=" + id + ":" + ThreadLoaclVariableHolder.get() + ‘}‘; } }
原理分析
public T get() { Thread t = Thread.currentThread(); //获取当前线程Thread对象中存放的ThreadLocalMap。 ThreadLocalMap map = getMap(t); //判断当前对象是否存在本地线程对象 if (map != null) { //判断当前线程对象中的threadLocals是否存储当前对象(注意这个this)的值 ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } //如果上述两个判断均不满足,则进行初始化 return setInitialValue(); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } //关于ThreadLocalMap类的定义请参考源码 public class Thread implements Runnable { /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null; }
/** *调用重写的initialValue()方法获取初始值, *然后将当前ThreadLocal的初始化值添加到Thread对象的threadLocals变量中。 **/ private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; } private void set(ThreadLocal<?> key, Object value) { // We don‘t use a fast path as with get() because it is at // least as common to use set() to create new entries as // it is to replace existing ones, in which case, a fast // path would fail more often than not. 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)]) { ThreadLocal<?> k = e.get(); if (k == key) { e.value = value; return; } if (k == null) { replaceStaleEntry(key, value, i); return; } } tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
ThreadLocal的副作用
参考:《Thinking In Java》、《Java并发编程实战》、《码出高效》
标签:nes 脏数据 map ice 回收 原理 java并发编程 静态 shutdown
原文地址:https://www.cnblogs.com/TryTired/p/10933014.html