線程相關類java
java還爲線程安全提供了一些工具類。數據庫
1、ThreadLocal類(Thread Local Variable)小程序
ThreadLocal類,是線程局部變量的意思。功用很是簡單,就是爲每個使用該變量的線程提供一個變量值的副本,使沒一個線程均可以獨立的改變本身的副本,而不會和其餘副本衝突。安全
ThreadLocal提供了3個public方法多線程
T get();返回此線程局部變量中當前線程副本中的值併發
void remove():刪除此線程局部變量中當前線程的值ide
void set(T value):設置此線程局部變量中當前線程副本中的值高併發
ThreadLocal也是爲了解決多線程中對同一變量訪問的衝突。普通的同步機制中是經過對象加鎖來實現對同一變量的安全訪問。工具
ThreadLocal從另外一角度來解決多線程的併發,它是將須要併發訪問的資源複製成多份,每一個線程擁有一份資源,不必對該變量進行同步了。this
ThreadLocal並不能代替同步機制,二者的問題領域不一樣,同步機制是爲了同步多個線程對相同的資源進行併發訪問,是多線程之間進行通訊的有效方式。ThreadLocal是爲了隔離多個線程的數據共享,從根本上避免多個線程之間對共享資源的競爭。
最多見的ThreadLocal使用場景爲 用來解決 數據庫鏈接、Session管理等。
下面小程序說明了ThreadLocal能達到在每一個線程中建立變量副本的效果:
package threadtest; public class ThreadTest implements Runnable{ private ThreadLocal<Integer> i =new ThreadLocal<>(); public int getI() { return i.get(); } public void setI(int i) { this.i.set(i); } @Override public void run() { for(i.set(0);i.get()<100;i.set(i.get()+1)) { System.out.println(Thread.currentThread().getName() + "--------->" + i.get()); } } public static void main(String[] args) { //兩個線程,各自打印各自的值 ThreadTest tt = new ThreadTest(); Thread t1 = new Thread(tt,"t1"); Thread t2 = new Thread(tt,"t2"); t1.start(); t2.start(); } }
結果:i變量兩個線程各自不影響
t1--------->0 t2--------->0 t1--------->1 t2--------->1 t1--------->2 t2--------->2 t1--------->3 t2--------->3 ... t2--------->94 t2--------->95 t2--------->96 t2--------->97 t2--------->98 t2--------->99 t1--------->15 t1--------->16 t1--------->17 t1--------->18 ... t1--------->97 t1--------->98 t1--------->99
2、包裝線程不安全的集合
Java集合中ArrayList,LinkedList,HashSet,TreeSet,HashMap,TreeMap等都是線程不安全的,就是多個線程併發向這些集合中存取數據,可能會破壞數據的完整性。
若是要多線程訪問這些集合,就須要包裝下,須要用到Collections提供的靜態方法把這些集合包裝成安全的集合,方法以下:
static <T> Collection<T> synchronizedCollection(Collection<T> c)
static <T> List<T> synchronizedList(List<T> list)
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
static <T> Set<T> synchronizedSet(Set<T> s)
static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
//將ArrayList包裝成安全的 List<String> l =Collections.synchronizedList(new ArrayList<String>());
3、線程安全的集合類
Java5開始,java.util.concurrent包下提供了大量支持高併發訪問的集合接口和實現類
主要分爲兩類:
以Concurrent開頭的集合類,如:ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentSkipListSet,ConcurrentLinkedQueue,ConcurrentLinkedDeque
以CopyOnWrite開頭的集合類,如: CopyOnWriteArrayList,CopyOnWriteArraySet.
其中Concurrent開頭的集合類表明了併發訪問的集合,支持多線程併發寫入訪問,這些寫入程序的全部操做都是線程安全的,但讀取不會鎖定。
當多個線程共享訪問一個公共集合時,ConcurrentLinkedQueue是一個不錯的選擇。ConcurrentLinkedQueue實現了多線程的高效訪問,個線程訪問時無需等待
在默認狀況下ConcurrentHashMap支持16個線程併發寫入,超過16個時,可能有些線程須要等待。