android ThreadLocal的原理解析和用法
来源:互联网 发布:在ubuntu运行apk软件 编辑:程序博客网 时间:2024/05/08 23:44
ThreadLocal是一个存储数据的一个类,主要用在不同线程数据的存储,每个线程都有自己的标志,线程间的数据是用共同的ThreadLocal的对象,但是存储数据值是不同的。下面通过一个小例子来了解用法。
在一个Activity内分别在2个子线程和主线程上分别存数据和取数据。
public class MainActivity extends AppCompatActivity { private ThreadLocal<String> mThreadLocal; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mThreadLocal = new ThreadLocal<>(); mThreadLocal.set("主线程"); Log.i("zhang------------------","threadMain值_"+mThreadLocal.get()); new Thread("ThreadOne"){ @Override public void run() { super.run(); mThreadLocal.set("线程一"); Log.i("zhang------------------","threadOne值_"+mThreadLocal.get()); } }.start(); new Thread("ThreadTwo"){ @Override public void run() { super.run(); mThreadLocal.set("线程二"); Log.i("zhang------------------","threadTwo值_"+mThreadLocal.get()); } }.start(); }}
运行结果如下:
03-19 16:15:40.533 6817-6817/? I/zhang------------------: threadMain值_主线程03-19 16:15:40.538 6817-6834/? I/zhang------------------: threadOne值_线程一03-19 16:15:40.542 6817-6835/? I/zhang------------------: threadTwo值_线程二
从运行结果可以看出不同线程访问的是同一ThreadLocal对象,但是在对应的线程内获取到的值是不一样的。这就很清楚的说明了ThreadLocal的实际用法了。
但是为什么ThreadLocal能做到不同线程中维护一套数据的副本且不相互影响了。
ThreadLocal内部的实现原理:从set方法和get方法分析。
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); }
通过getMap中传递线程标志得到一个可以存储数据的ThreadLocalMap,不为null就存储,空的话就new一个ThreadLocalMap();下面我们来看看怎样用map.set(this,value)内部是怎样实现的吧。
红色关键部分。
private void set(ThreadLocal key, Object value) { 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(); }
内部由一个Entry[ ]键值对数据来存储的,这键值对Entry < ThreadLoacl key,Object value >,通过一些算法等来判断将value值储存起来。 即内部有个存储value的数组Entry。
下面来分析get的方法
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(); }
代码逻辑也很清晰。通过线程标志获取对应的ThreadLocalMap,接着获取内部的键值对Entry数据,然后取出值。
总结:从set和get的从可以分析出他们都是操作当前线程的ThreadLocalMap内部的键值对Entry数组,,所有的存储和读取数据都是在各自的对应的线程标志内完成。通过分析可以更加清楚上面的小例子中输出结果共用一个对象但互不影响他们在各自线程中数据的存取的原因了。
- android ThreadLocal的原理解析和用法
- ThreadLocal用法和原理
- ThreadLocal的用法、原理和用途
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法和实现原理
- ThreadLocal用法详解和原理
- Android消息机制之ThreadLocal原理解析
- ThreadLocal的用法和作用
- SpringMVC <mvc:resources mapping=“”/> 标签
- TCP socket 简单实现
- 改NavigationView的MenuItem的字体颜色并修改默认选中的item
- js数组操作:增删改查(更新中3.28……)
- 模板方法模式
- android ThreadLocal的原理解析和用法
- 多线程复制自己写
- 278 First Bad Version 【拓展分析,自己出题】
- 欢迎使用CSDN-markdown编辑器
- Matlab里面的数据类型
- Ubuntu(3节点)+CDH
- Java虚拟机1
- 简单!Android环境搭建
- 《git 版本控制管理》学习笔记