java中ThreadLocal

ThreadLocal可以爲每個線程保存一份數據,相當與線程私有數據,不會被別的線程共享。
Thread.class

ThreadLocal.ThreadLocalMap threadLocals = null;  key爲ThreadLocal實例,value要保存的數據

這樣可以看得出來每個線程都會擁有一個單獨的ThreadLocal.ThreadLocalMap(它是ThreadLocal一個靜態內部類)
ThreadLocal.class

 //爲當前線程寫入值
 public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t); //每個線程都有一個ThreadLocalMap
    if (map != null)
        map.set(this, value);  //更新<ThreadLocal , value>
    else
        createMap(t, value);   //根據當前線程創建ThreadLocalMap
 }
 ThreadLocalMap getMap(Thread t) {
       return t.threadLocals;
 }
 void createMap(Thread t, T firstValue) {
      t.threadLocals = new ThreadLocalMap(this, firstValue);  //充分說明了每個線程都有獨立的一個ThreadLocalMap
 }
 //根據當前線程獲取值(真正獲取值的時候是根據ThreadLocal實例來獲取的)
 public T get() {
     Thread t = Thread.currentThread();
     ThreadLocalMap map = getMap(t);
     if (map != null) {
         ThreadLocalMap.Entry e = map.getEntry(this);
         if (e != null) {
             @SuppressWarnings("unchecked")
             T result = (T)e.value;
             return result;
         }
     }
     return setInitialValue();  //獲取的時候發現當前線程沒有ThreadMap就會初始化一個
  }
  private T setInitialValue() {
       T value = initialValue();
       Thread t = Thread.currentThread();
       //爲什還要獲取一遍判斷一遍?感覺不用呀
       ThreadLocalMap map = getMap(t);
       if (map != null)
           map.set(this, value);
       else
           createMap(t, value);
       return value;
  }

每個線程都有一個ThreadMap<ThreadLocal,value>,這樣Thread可以擁有多個ThreadLocal
還有那個疑問暫時不知道爲什麼?

附帶一個例子:每個線程維持自己的一個數據庫連接

public class ConnectionFactory {
    private static ThreadLocal<Connection> connections = new ThreadLocal<Connection>();
    private static String URL = "jdbc:mysql://127.0.0.1:3306/xia";
    private static String USER = "root";
    private static String PASSWORD = "123";
    public static Connection getConnectionInstance() {
        System.out.println(Thread.currentThread().getName() + "獲取Connection");
        Connection conn = connections.get();
        if (conn != null) {
            return conn;
        }
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(URL, USER, PASSWORD);
            connections.set(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
}
public class ConnectionTest {
    public static void main(String[] args) {
        Connection conn_1 = ConnectionFactory .getConnectionInstance();
        Connection conn_2 = ConnectionFactory .getConnectionInstance();
        System.out.println(conn_1 == conn_2);
        new Thread(new Runnable() {
            Connection conn_3 = null;
            Connection conn_4 = null;

            @Override
            public void run() {
                conn_3 = ConnectionFactory .getConnectionInstance();
                conn_4 = ConnectionFactory .getConnectionInstance();
                System.out.println(conn_1 == conn_3);
                System.out.println(conn_3 == conn_4);
            }
        }).start();
    }
}

運行結果:

main獲取Connection
Thu Jun 02 14:53:30 CST 2016 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
main獲取Connection
true
Thread-0獲取Connection
Thu Jun 02 14:53:30 CST 2016 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Thread-0獲取Connection
false
true
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章