ThreadLocal的入門代碼實踐及使用和實現原理

 

爲解決多線程程序的併發問題提供了一種新的思路。使用這個工具類可以很簡潔地編寫出優美的多線程程序,ThreadLocal並不是一個 Thread ,而是 Thread 的局部變量。

查看Thread 源碼可得知:

 /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

ThreadLocal 原理:每個線程的內部都維護了一個 ThreadLocalMap,它是一個 Map(key,value)數據格式,key 是一個弱引用,也就是 ThreadLocal 本身,而 value 存的是線程變量的值。

直接運行一段代碼

/**
 * 36ThreadLocal 使用及實現原理
 * 
Thread-0  1
Thread-1  1
Thread-2  1

Thread-0  2
Thread-1  2
Thread-2  2

Thread-1  3
Thread-0  3
Thread-2  3
 * @author Administrator
 */
public class Demo38ThreadLocal {
	private ThreadLocal<Integer> count = new ThreadLocal<Integer>(){
		@Override
		protected Integer initialValue() {
			return new Integer(0);
		}
	};

	public int getNext() {
		Integer value = count.get();
		value++;
		count.set(value);
		return value;
	}

	public static void main(String[] args) {
		Demo38ThreadLocal demo = new Demo38ThreadLocal();
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					System.out.println(Thread.currentThread().getName() +"  "+demo.getNext());
					try {
						Thread.sleep(1000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					System.out.println(Thread.currentThread().getName() +"  "+ demo.getNext());
					try {
						Thread.sleep(1000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					System.out.println(Thread.currentThread().getName() +"  "+ demo.getNext());
					try {
						Thread.sleep(1000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
}

       

 線程資源持有

線程獨立資源持有是threadlocal最常用的使用方式,比如從單線程應用擴展到多線程應用。

 線程資源一致性 

  

Entry數組的長度爲啥一定要是2的冪

  

Hash 衝突

ThreadLocalMap 中解決 Hash 衝突的方式並非鏈表的方式,而是採用線性探測的方式.

所謂線性探測,就是根據初始 key 的 hashcode 值確定元素在 table 數組中的位置,如果發現這個位置上已經被其他的 key 值佔用,則利用固定的算法尋找一定步長的下個位置,依次判斷,直至找到能夠存放的位置。

 

ThreadLocal特性

ThreadLocal和Synchronized都是爲了解決多線程中相同變量的訪問衝突問題,不同的點是

  • Synchronized是通過線程等待,犧牲時間來解決訪問衝突
  • ThreadLocal是通過每個線程單獨一份存儲空間,犧牲空間來解決衝突,並且相比於Synchronized,ThreadLocal具有線程隔離的效果,只有在線程內才能獲取到對應的值,線程外則不能訪問到想要的值。

內存泄漏

ThreadLocal 應用場景 

  • 線程間數據隔離,各線程的 ThreadLocal 互不影響
  • 方便同一個線程使用某一對象,避免不必要的參數傳遞
  • 全鏈路追蹤中的 traceId 或者流程引擎中上下文的傳遞一般採用 ThreadLocal
  • Spring 事務管理器採用了 ThreadLocal
  • Spring MVC 的 RequestContextHolder 的實現使用了 ThreadLocal

 

 

ThreadLocal問了父子線程怎麼共享數據 interitableThreadLocals

https://blog.csdn.net/hewenbo111/article/details/80487252?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

InheritableThreadLocal與阿里的TransmittableThreadLocal設計思路解析

https://blog.csdn.net/u010833547/article/details/99647118?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章