標籤:read tostring exception nts 副本 get final tty start
首先,ThreadLocal 不是用來解決共用對象的多線程訪問問題的,一般情況下,通過ThreadLocal.set() 到線程中的對象是該線程自己使用的對象,其他線程是不需要訪問的,也訪問不到的。各個線程中訪問的是不同的對象。
另外,說ThreadLocal使得各線程能夠保持各自獨立的一個對象,並不是通過ThreadLocal.set()來實現的,而是通過每個線程中的new 對象 的操作來建立的對象,每個線程建立一個,不是什麼對象的拷貝或副本。通過ThreadLocal.set()將這個新建立的對象的引用儲存到各線程的自己的一個map中,每個線程都有這樣一個map,執行ThreadLocal.get()時,各線程從自己的map中取出放進去的對象,因此取出來的是各自自己線程中的對象,ThreadLocal執行個體是作為map的key來使用的。
如果ThreadLocal.set()進去的東西本來就是多個線程共用的同一個對象,那麼多個線程的ThreadLocal.get()取得的還是這個共用對象本身,還是有並發訪問問題。
總結: ThreadLocal.set()進去的對象會存在當前線程中的一個map中,並以當前ThreadLocal本身作為key,只能說這個map能保證唯一,map中存的對象如果是通過new存進去的話,沒被另一個線程引用繼續存入的話,則該對象對於該線程唯一,否則因是參考型別,可能存在多線程並發問題
測試代碼:
public static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); public static void main(String[] args) { Object[] objects = new Object[]{1,2}; System.out.println(Arrays.toString(objects)); // // for (int i = 0; i< 10 ;i++) { // // final int j= i ; // new Thread(new Runnable() { // // @Override // public void run() { // // threadLocal.set(j+"-----------"+Thread.currentThread().getId()+"-----"+threadLocal.hashCode()); // Thread.currentThread().getId(); // try { // Thread.currentThread().sleep(1000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // System.out.println(threadLocal.get()+"----------"+Thread.currentThread().getId()+"------"+"-----"+threadLocal.hashCode()); // } // }).start(); // }
java 中的 ThreadLocal