通常我们要实现线程安全,可以使用2种方案:一种是同步,同步代码块中,同一时间,只能有一个线程进行处理,该方案是以时间为代价来换取线程安全;另一种方案是,使用线程本地对象,每个线程都有独立的变量版本,不会产生相互干扰,该方案是以空间为代价来换取线程安全。 使用线程本地对象创建的变量,每个线程都会存在变量的一个副本,修改其中一个副本,并不会影响其他副本的值。 本文讨论的主题——ThreadLocal就是一个线程本地对象类,可以用它来实现线程本地对象的创建、使用、删除等逻辑。 ThreadLocal使用场景非常的多,例如,我们可以在变量需要线程私有的情况下使用,以确保线程之间私有变量的独立性;我们还可以在某些时候使用线程本地变量解决线程同步的问题,在需要同步的地方,使用ThreadLocal来定义变量,可以避免锁等待,大大提高了执行效率。 在Android Handler消息机制中,就用到了ThreadLocal,用它来实现每个线程都有独立的Looper对象的问题。其实在Android中,线程本地对象有大量的使用,这里只是简单列举2个。 Looper对象使用线程本地对象,实现了每个线程中,都存在一个线程自己的Looper对象,并且实现了每个线程独立的loop消息循环。 Receiver处理时,也用到了线程本地对象。 接下来,我们来分析线程本地对象的实现原理。 Java虚拟机在执行代码的时,内存区域以是否是线程私有可以分为2大部分:线程私有区域和线程共享区域。 线程私有区域包含: 如果我们的变量创建并运行在线程私有区域,则它天然就支持了线程私有。那么ThreadLocal是这样吗?根据我们的常用的使用场景和实例来看,很明显它不是! ThreadLocal又是如何实现线程私有的呢? 我们从源码来分析它的实现。 它有一个空构造函数,只是创建了一个ThreadLocal对象。 当创建一个ThreadLocal对象后,我们需要调用set方法来设置线程本地对象的值,使用get方法来获取对象值。 我们来看线程本地对象的列表是如何声明和存储的。 getMap方法返回的是当前线程的threadLocals对象。 threadLocals对象,是ThreadLocal静态内部类ThreadLocalMap的对象。 ThreadLocalMap负责存储当前线程中的所有线程本地对象,它是一个自定义的容器类。 ThreadLocal的set方法,调用ThreadLocalMap的set方法来添加元素。 ThreadLocal的get方法,调用ThreadLocalMap的getEntry方法来获取元素。 本文分析了ThreadLocal实现线程本地对象的原理及源码解析。我们来总结一下:
概述
使用场景
Looper类
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
ActivityThread类
private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
原理分析
线程私有内存区域
ThreadLocal源码分析
构造函数
public ThreadLocal() { }
set/get方法
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } 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(); }
逻辑解析:
线程本地对象的存储列表
ThreadLocal的getMap方法:
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
Thread类中的定义:
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal静态内部类ThreadLocalMap
ThreadLocalMap初始化
static class ThreadLocalMap { private static final int INITIAL_CAPACITY = 16; static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } private Entry[] table; ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } }
我们来看它的添加元素的方法:
private void set(ThreadLocal<?> key, Object value) { …… tab[i] = new Entry(key, value); …… }
获得对象的getEntry方法:
private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); }
总结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算