https://www.zhihu.com/question/35250439
結論:
1 static 防止無意義多實例
2 當static時,ThreadLocal ref生命延長-ThreadMap的key在線程生命期內始終有值-ThreadMap的value在線程生命期內不釋放——故線程池下,static修飾TrheadLocal引用,必須(1)remove 或(2)手動 ThreadLocal ref = null
兩個例子:
A 《多線程實戰》上ThreadLocal的一個實例
作者測試的順序:
1 創建10000個runnable對象放入max 10的線程池,創建10個Thread,即10個~Map;
2 新建ThreadLocal(1)對象,調用get/set,產生10個SimpleDateFormat對象;
3 static ThreadLocal red = null ,此時ThreadLocal對象僅有一個弱引用,在Thread.~Map中;
4 第一次gc,回收了ThreadLocal對象,同時致使 Thread.~Map中存在10個key為null的value;
5 再創建10000個runnable對象,放入線程池原先的10個線程;
6 新建ThreadLocal(2)對象,調用set,觸發新變量加入Thread.~Map,進而觸發中key為null的value對象被置為可回收對象,原先的value對象與Thread的強引用斷開
7 第二次gc,正式回收被與Thread斷開強引用的10個SimpleDateFormat對象
B 模仿spring事務框架時的一個數據庫連接例子
Java事務處理全解析(四)—— 成功的案例(自己實現一個線程安全的TransactionManager)
http://blog.csdn.net/huilangeliuxin/article/details/43446733
這篇文章中有個實例:
定義一個線程安全的SingleThreadConnectionHolder類如下:
- public class SingleThreadConnectionHolder
- {
- private static ThreadLocal<ConnectionHolder> localConnectionHolder = new ThreadLocal<ConnectionHolder>();
- public static Connection getConnection(DataSource dataSource) throws SQLException
- {
- return getConnectionHolder().getConnection(dataSource);
- }
- public static void removeConnection(DataSource dataSource)
- {
- getConnectionHolder().removeConnection(dataSource);
- }
- private static ConnectionHolder getConnectionHolder()
- {
- ConnectionHolder connectionHolder = localConnectionHolder.get();
- if (connectionHolder == null)
- {
- connectionHolder = new ConnectionHolder();
- localConnectionHolder.set(connectionHolder);
- }
- return connectionHolder;
- }
- }
可以看到,每次事務提交后,都調用remove,防止連接泄露