- /**
- * 數據庫連接管理類
- * @author 爽
- *
- */
- public class ConnectionManager {
- /** 線程內共享Connection,ThreadLocal通常是全局的,支持泛型 */
- private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
- public static Connection getCurrConnection() {
- // 獲取當前線程內共享的Connection
- Connection conn = threadLocal.get();
- try {
- // 判斷連接是否可用
- if(conn == null || conn.isClosed()) {
- // 創建新的Connection賦值給conn(略)
- // 保存Connection
- threadLocal.set(conn);
- }
- } catch (SQLException e) {
- // 異常處理
- }
- return conn;
- }
- /**
- * 關閉當前數據庫連接
- */
- public static void close() {
- // 獲取當前線程內共享的Connection
- Connection conn = threadLocal.get();
- try {
- // 判斷是否已經關閉
- if(conn != null && !conn.isClosed()) {
- // 關閉資源
- conn.close();
- // 移除Connection
- threadLocal.remove();
- conn = null;
- }
- } catch (SQLException e) {
- // 異常處理
- }
- }
- }
這樣處理的好處:
- 統一管理Connection;
- 不需要顯示傳參Connection,代碼更優雅;
- 降低耦合性。
ThreadLocal有四個方法,分別爲:
initialValue
protected T initialValue()
- 返回此線程局部變量的當前線程的初始值。最多在每次訪問線程來獲得每個線程局部變量時調用此方法一次,即線程第一次使用
get()
方法訪問變量的時候。如果線程先於 get 方法調用set(T)
方法,則不會在線程中再調用 initialValue 方法。該實現只返回 null;如果程序員希望將線程局部變量初始化爲 null 以外的某個值,則必須爲 ThreadLocal 創建子類,並重寫此方法。通常,將使用匿名內部類。initialValue 的典型實現將調用一個適當的構造方法,並返回新構造的對象。
-
- 返回:
- 返回此線程局部變量的初始值
get
public T get()
- 返回此線程局部變量的當前線程副本中的值。如果這是線程第一次調用該方法,則創建並初始化此副本。
-
- 返回:
- 此線程局部變量的當前線程的值
set
public void set(T value)
- 將此線程局部變量的當前線程副本中的值設置爲指定值。許多應用程序不需要這項功能,它們只依賴於
initialValue()
方法來設置線程局部變量的值。 -
- 參數:
value
- 存儲在此線程局部變量的當前線程副本中的值。
remove
public void remove()
- 移除此線程局部變量的值。這可能有助於減少線程局部變量的存儲需求。如果再次訪問此線程局部變量,那麼在默認情況下它將擁有其 initialValue。
很多人對ThreadLocal存在一定的誤解,說ThreadLocal中有一個全局的Map,set時執行map.put(Thread.currentThread(), value),get和remove時也同理,但SUN的大師們是否是如此實現的,我們只能去看源碼了。
set方法:
- /**
- * Sets the current thread's copy of this thread-local variable
- * to the specified value. Most subclasses will have no need to
- * override this method, relying solely on the {@link #initialValue}
- * method to set the values of thread-locals.
- *
- * @param value the value to be stored in the current thread's copy of
- * this thread-local.
- */
- public void set(T value) {
- // 獲取當前線程對象
- Thread t = Thread.currentThread();
- // 獲取當前線程本地變量Map
- ThreadLocalMap map = getMap(t);
- // map不爲空
- if (map != null)
- // 存值
- map.set(this, value);
- else
- // 創建一個當前線程本地變量Map
- createMap(t, value);
- }
- /**
- * Get the map associated with a ThreadLocal. Overridden in
- * InheritableThreadLocal.
- *
- * @param t the current thread
- * @return the map
- */
- ThreadLocalMap getMap(Thread t) {
- // 獲取當前線程的本地變量Map
- return t.threadLocals;
- }
這裏注意,ThreadLocal中是有一個Map,但這個Map不是我們平時使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個內部類,不對外使用的。當使用ThreadLocal存值時,首先是獲取到當前線程對象,然後獲取到當前線程本地變量Map,最後將當前使用的ThreadLocal和傳入的值放到Map中,也就是說ThreadLocalMap中存的值是[ThreadLocal對象, 存放的值],這樣做的好處是,每個線程都對應一個本地變量的Map,所以一個線程可以存在多個線程本地變量。
get方法:
- /**
- * Returns the value in the current thread's copy of this
- * thread-local variable. If the variable has no value for the
- * current thread, it is first initialized to the value returned
- * by an invocation of the {@link #initialValue} method.
- *
- * @return the current thread's value of this thread-local
- */
- public T get() {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null) {
- ThreadLocalMap.Entry e = map.getEntry(this);
- if (e != null)
- return (T)e.value;
- }
- // 如果值爲空,則返回初始值
- return setInitialValue();
- }
(完)
本文來自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/15732053