對象的使用和共享:ThreadLocal
阿新 • • 發佈:2018-04-30
優點 使用 允許 read 不可變對象 可變 講解 ger 多線程 2.
1. 引言
在多線程環境下,使用和共享對象時有四種常用策略:
- 線程封閉:線程封閉的對象只能由一個線程擁有,線程封閉在線程中,並且只能由這個線程修改。實現技術有==棧封閉==和 ==
ThreadLocal
== 類; - 只讀共享:只允許讀取的且不可修改的對象可以由多個線程安全的並發訪問。不可變對象和事實不可變對象此類策略的實現技術;
- 保護對象:使用特定的鎖訪問對象;
- 線程安全的共享:在對象內部實現同步,並且只使用共有接口提供訪問對象狀態——不太理解。
2. ThreadLocal
基本思想
實現線程封閉的方式之一是棧封閉,只能通過局部變量才能訪問對象,而局部變量是封閉在執行的線程中的,其他線程無法修改。另一片博文展開講解。
優點
ThreadLocal
是為每個使用變量的線程都存有一個獨立的副本,因此每個線程對此變量的修改都是都只是在自己工作內存而已,也沒有同步內存的時間開銷。因此也可以說棧封閉是用空間換時間和安全性。
使用場景
如果對象的分配開銷特別高或者在線程中執行的頻率特別高,則應該使用ThreadLocal。
3. 實現
主要方法
T iniinitialValue()
:初始化當前線程副本值;T get()
:返回此線程中thread-local變量副本值,如果當前線程沒有對應副本值,則會調用iniinitialValue
方法返回;set(T value)
:設置當前線程副本值;remove()
:移除當前線程局部變量副本值。
示例:
public class ThreadLocalDemo implements Runnable { private static ThreadLocal<Integer> threadLocalVal=new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return 1; } }; public Integer getThreadLocalVal() { return threadLocalVal.get();//fixme 返回的只是Integer變量的副本而已 } @Override public void run() { Integer i=threadLocalVal.get(); while(true){ System.out.println(i++); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Thread(new ThreadLocalDemo()).start(); new Thread(new ThreadLocalDemo()).start(); } }
對象的使用和共享:ThreadLocal