java中ThreadLocal的使用
文章目錄
- 在Map中存儲用戶數據
- 在ThreadLocal中存儲用戶數據
java中ThreadLocal的使用
ThreadLocal主要用來為當前線程存儲數據,這個數據只有當前線程可以訪問。
在定義ThreadLocal的時候,我們可以同時定義存儲在ThreadLocal中的特定類型的對象。
ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();上面我們定義了一個存儲Integer的ThreadLocal對象。
要存儲和獲取ThreadLocal中的對象也非常簡單,使用get()和set()即可:
threadLocalValue.set(1); Integer result = threadLocalValue.get();我可以將ThreadLocal看成是一個map,而當前的線程就是map中的key。
除了new一個ThreadLocal對象,我們還可以通過:
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {return new SuppliedThreadLocal<>(supplier);}ThreadLocal提供的靜態方法withInitial來初始化一個ThreadLocal。
ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);withInitial需要一個Supplier對象,通過調用Supplier的get()方法獲取到初始值。
要想刪除ThreadLocal中的存儲數據,可以調用:
threadLocal.remove();下面我通過兩個例子的對比,來看一下使用ThreadLocal的好處。
在實際的應用中,我們通常會需要為不同的用戶請求存儲不同的用戶信息,一般來說我們需要構建一個全局的Map,來根據不同的用戶ID,來存儲不同的用戶信息,方便在后面獲取。
在Map中存儲用戶數據
我們先看下如果使用全局的Map該怎么用:
public class SharedMapWithUserContext implements Runnable {public static Map<Integer, Context> userContextPerUserId= new ConcurrentHashMap<>();private Integer userId;private UserRepository userRepository = new UserRepository();public SharedMapWithUserContext(int i) {this.userId=i;}@Overridepublic void run() {String userName = userRepository.getUserNameForUserId(userId);userContextPerUserId.put(userId, new Context(userName));} }這里我們定義了一個static的Map來存取用戶信息。
再看一下怎么使用:
@Testpublic void testWithMap(){SharedMapWithUserContext firstUser = new SharedMapWithUserContext(1);SharedMapWithUserContext secondUser = new SharedMapWithUserContext(2);new Thread(firstUser).start();new Thread(secondUser).start();assertEquals(SharedMapWithUserContext.userContextPerUserId.size(), 2);}在ThreadLocal中存儲用戶數據
如果我們要在ThreadLocal中使用可以這樣:
public class ThreadLocalWithUserContext implements Runnable {private static ThreadLocal<Context> userContext= new ThreadLocal<>();private Integer userId;private UserRepository userRepository = new UserRepository();public ThreadLocalWithUserContext(int i) {this.userId=i;}@Overridepublic void run() {String userName = userRepository.getUserNameForUserId(userId);userContext.set(new Context(userName));System.out.println("thread context for given userId: "+ userId + " is: " + userContext.get());}}測試代碼如下:
public class ThreadLocalWithUserContextTest {@Testpublic void testWithThreadLocal(){ThreadLocalWithUserContext firstUser= new ThreadLocalWithUserContext(1);ThreadLocalWithUserContext secondUser= new ThreadLocalWithUserContext(2);new Thread(firstUser).start();new Thread(secondUser).start();} }運行之后,我們可以得到下面的結果:
thread context for given userId: 1 is: com.flydean.Context@411734d4 thread context for given userId: 2 is: com.flydean.Context@1e9b6cc不同的用戶信息被存儲在不同的線程環境中。
注意,我們使用ThreadLocal的時候,一定是我們可以自由的控制所創建的線程。如果在ExecutorService環境下,就最好不要使用ThreadLocal,因為在ExecutorService中,線程是不可控的。
本文的例子可以參考https://github.com/ddean2009/learn-java-concurrency/tree/master/ThreadLocal
更多精彩內容且看:
- 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程
更多教程請參考 flydean的博客
總結
以上是生活随笔為你收集整理的java中ThreadLocal的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中Runnable和Callab
- 下一篇: java中线程的生命周期