极速赛车APP下载

threadlocal static_threadlocal remove_c# threadlocal

电脑杂谈  发布时间:2019-08-31 10:01:57  来源:网络整理

threadlocal remove_c# threadlocal_threadlocal static

与Synchonized的对照: ThreadLocal和Synchonized都用于缓解多线程并发訪问。可是ThreadLocal与synchronized有本质的差异。synchronized是运用锁的模式,使函数或代码块在某一时该只是能被一个线程訪问。而ThreadLocal为每个线程都提供了函数的副本,使得每个线程在某一时间訪问到的只是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却刚好相反,它用于在多个线程间通信时可以获得数据共享。

Synchronized用于线程间的数据共享threadlocal static,而ThreadLocal则用于线程间的数据隔离。

用法

把要线程隔离的数据放进ThreadLocal

1static ThreadLocal<T> threadLocal = new ThreadLocal<T>() {

2 protected T initialValue() {

3 这里一般new一个对象返回

4 }

5}

线程获得相关数据的之后即使

1threadLocal.get();

想设置、赋值只要

极速赛车APP下载1threadLocal.set(val)

使用场景

如下面说到的,ThreadLocal是用于线程间的数据隔离,ThreadLocal为每个线程都提供了函数的副本。

原理分析

1、get()方法

1public T get() {

2 Thread t = Thread.currentThread();

3 ThreadLocalMap map = getMap(t);

4 if (map != null) {//当map已存在

5 ThreadLocalMap。Entry e = map。getEntry(this);

6 if (e != null) {

7 @SuppressWarnings("unchecked")

8 T result = (T)e.value;

9 return result;

10 }

11 }

12 return setInitialValue();//初始化值

13}

14

c# threadlocal_threadlocal static_threadlocal remove

15ThreadLocalMap getMap(Thread t) {

16 return t.threadLocals;

17}

上面先取到当前线程,然后读取getMap方法获取对应的ThreadLocalMap,ThreadLocalMap是ThreadLocal的静态内部类,然后Thread类中有一个这样类型成员,所以getMap是直接返回Thread的成员

1ThreadLocal.ThreadLocalMap threadLocals = null;

来看下ThreadLocal的内部类ThreadLocalMap源码,留个大概印象

极速赛车APP下载1static class ThreadLocalMap {

极速赛车APP下载2 private static final int INITIAL_CAPACITY = 16;//初始数组大小

3 private Entry[] table;//每个可以拥有多个ThreadLocal

4 private int size = 0;

5 private int threshold;//扩容阀值

6 static class Entry extends WeakReference<ThreadLocal<?>> {

7 Object value;

8

极速赛车APP下载9 Entry(ThreadLocal<?> k, Object v) {

10 super(k);

11 value = v;

12 }

13 }

14

15 private Entry getEntry(ThreadLocal<?> key) {

16 int i = key。threadLocalHashCode & (table。length - 1);

17 Entry e = table[i];

18 if (e != null && e.get() == key)

19 return e;

20 else

极速赛车APP下载21 return getEntryAfterMiss(key, i, e);

22 }

23

24 private void set(ThreadLocal<?> key, Object value) {

25 Entry[] tab = table;

threadlocal static_c# threadlocal_threadlocal remove

26 int len = tab。length;

极速赛车APP下载27 int i = key。threadLocalHashCode & (len-1);

28 for (Entry e = tab[i];

29 e != null;

30 e = tab[i = nextIndex(i, len)]) {

31 ThreadLocal<?> k = e.get();

32 if (k == key) {

33 e.value = value;

34 return;

35 }

36 if (k == null) {

37 //循环利用key过期的Entry

38 replaceStaleEntry(key, value, i);

39 return;

40 }

41 }

42 tab[i] = new Entry(key, value);

43 int sz = ++size;

44 if (!cleanSomeSlots(i, sz) && sz >= threshold)

45 rehash();

46 }

47 ...

48}

极速赛车APP下载可以发现有个Entry内部静态类,它继承了WeakReference,总之它记录了两个信息,一个是ThreadLocal<?>类型,一个是Object类型的值。getEntry方法则是获得某个ThreadLocal对应的值,set方式就是更新或数组相应的ThreadLocal对应的值。里面涵盖到扩容策略、Entry哈希冲突、循环运用等等不再深入,留个大概印象就好。

回顾下get()方法中的代码

极速赛车APP下载1if (map != null) {

2 ThreadLocalMap.Entry e = map.getEntry(this);

3 if (e != null) {

4 @SuppressWarnings("unchecked")

5 T result = (T)e.value;

6 return result;

threadlocal static_threadlocal remove_c# threadlocal

7 }

8}

9return setInitialValue();

map为null或e为null经常走到setInitialValue,如果我们是第一次get()方法,那map会是空的,所以接下来先看setInitialValue()方法

1private T setInitialValue() {

2 //调用我们实现的方式给与需要线程隔离的值

3 T value = initialValue();

4 Thread t = Thread.currentThread();

5 //拿到相应线程的ThreadLocalMap成员变量

6 ThreadLocalMap map = getMap(t);

7 if (map != null)

8 map.set(this, value);

9 else

10 createMap(t, value);

11 return value;

12}

上面initialValue就是实例化ThreadLocal要推动的方式,这里又取了线程的ThreadLocalMap,不为空就把值set下去(键为TreadLocal本身,值就是initialValue返回的值);为空就建立一个map同时添加一个值出来,最后返回value。

map.set(this, value)这句代码在里面的ThreadLocalMap源码中可以发现大概步骤,下面说说createMap()做了什么事

极速赛车APP下载1void createMap(Thread t, T firstValue) {

2 t.threadLocals = new ThreadLocalMap(this, firstValue);

3}

4

5

6ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {

7 table = new Entry[INITIAL_CAPACITY];

8 int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);

9 //创建一个Entry,加入数组

极速赛车APP下载10 table[i] = new Entry(firstKey, firstValue);

11 size = 1;

12 setThreshold(INITIAL_CAPACITY);

13}

c# threadlocal_threadlocal static_threadlocal remove

可以看到在new ThreadLocalMap之后,就会创建一个Entry加入到数组中,最后把ThreadLocalMap的引用数组给Thread的threadLocals成员变量

在回顾下get()方法中的代码

1if (map != null) {

2 ThreadLocalMap.Entry e = map.getEntry(this);

3 if (e != null) {

极速赛车APP下载4 @SuppressWarnings("unchecked")

5 T result = (T)e.value;

6 return result;

7 }

8}

9return setInitialValue();

极速赛车APP下载现在map不会为空了,再次调用get方式都会调用map的getEntry方法(上面的ThreadLocalMap源码中可以发现大概步骤),拿到相应的Entry,然后就可以获得相应的值返回出去

2、set方式

分析完get()方法,那么set()方法就自然而然的知道了,就不再赘述

1public void set(T value) {

2 Thread t = Thread.currentThread();

3 ThreadLocalMap map = getMap(t);

4 if (map != null)

5 map.set(this, value);

6 else

7 createMap(t, value);

8}

总结

ThreadLocal的推动原理是,在每个线程中维护一个Map,键是ThreadLocal类型,值是Object类型。当想获得ThreadLocal的值时,就从当前线程中拿出Map,然后在把ThreadLocal本身成为键从Map中拿出值返回。

提供线程内的局部变量。每个线程都自己管控自己的局部变量,互不影响

内存泄漏问题。可以发现ThreadLocalMap中的Entry是继承WeakReference的threadlocal static极速赛车APP下载,其中ThreadLocal是以弱引用方式存在Entry中,如果ThreadLocal在内部没有被强引用,那么垃圾回收的之后才会被回收掉,又由于Entry中的value是强引用,就会发生存储泄露。虽然ThreadLocal源码中的会对这些状况进行了处理,但还是建议不需要用TreadLocal的之后,手动调remove方法。

架构技术进阶资料

+q q-q u n:948 368 769(免费获取以下资料)

极速赛车APP下载+q q-q u n:948 368 769(免费获取以下资料)


本文来自电脑杂谈,转载请注明本文网址:
http://www.0531mai.com/a/jisuanjixue/article-121194-1.html

    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    极速赛车手机官网 极速赛车手机版下载 极速赛车手机版下载 极速赛车APP 极速赛车双面盘 极速赛车双面盘 极速赛车手机版下载 极速赛车手机版下载 极速赛车APP 极速赛车手机版下载