本文對ThreadLocal類和Future接口進行了總結概括,包括ThreadLocal類的原理、內存泄露等問題,和Future接口的使用等問題。
一、ThreadLocal
1. 介紹
ThreadLocal(線程局部變量)是Java中的一個類,線程通過維護一個本地變量副本,從而保證對該變量的訪問不受其他線程的影響。
2. 實現原理
- 每個線程中都有一個ThreadLocalMap 類型的threadLocals 變量和 一個 inheritableThreadLocals 變量
- ThreadLocalMap是ThreadLocal的靜態內部類,存儲的是以ThreadLocal實例為 key ,Object 對象為 value 的鍵值對
- 當調用ThreadLocal類實例的get和set方法修改變量值的時候實際上調用的是ThreadLocalMap類的get和set方法,數據實際存儲在ThreadLocalMap中
- 源碼
① get方法
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();
}
② set方法
public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {map.set(this, value);} else {createMap(t, value);}
}ThreadLocalMap getMap(Thread t) {return t.threadLocals;
}void createMap(Thread t, T firstValue) {t.threadLocals = new ThreadLocalMap(this, firstValue);
}
3. 內存泄漏問題
(1)虛引用、弱引用、軟引用和強引用
- 虛引用:主要用于在對象被回收時,進行一些后續處理工作;必須和引用隊列(ReferenceQueue)聯合使用
- 弱引用:主要用于實現規范化映射;當垃圾收集器運行時,無論內存是否充足都會回收這些對象
- 軟引用:要用于實現內存敏感的緩存;在垃圾收集器判斷內存不足時,會回收這些對象
- 強引用:當一個對象被強引用時,垃圾收集器不會回收該對象,即使內存不足也不會回收。通過new對象實例可以創建。
(2)ThreaLocal內存泄露是因為ThreadLocalMap 中的 key 為 ThreadLocal 的弱引用,而 value 是強引用,因此當垃圾回收時會回收ThreadLocal對象實例,而與之對應的value不會被回收,之后該value也不能再使用,由此導致內存泄露。
注:使用ThreadLocal時一定要手動調用remove()方法
二、 Future接口
1. 介紹
Future 接口提供了一種處理異步計算結果的機制,通過使用 Future 和 其實現類FutureTask,可以方便地處理并發編程中的異步任務管理。
2. 常用方法
方法 | 描述 |
---|---|
boolean cancel(boolean mayInterruptIfRunning) | 嘗試取消任務的執行。如果任務已完成或已被取消,返回 false 。mayInterruptIfRunning 指示是否應該中斷正在執行的任務。 |
boolean isCancelled() | 如果任務在完成前被取消,則返回 true 。 |
boolean isDone() | 如果任務已完成(無論是正常完成、異常終止還是取消),返回 true 。 |
V get() throws InterruptedException, ExecutionException | 等待任務完成并獲取結果。如果任務執行過程中拋出異常,則拋出 ExecutionException 。若當前線程被中斷,拋出 InterruptedException 。 |
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException | 在指定時間內等待任務完成并獲取結果。如果在指定時間內任務沒有完成,拋出 TimeoutException 。若任務執行過程中拋出異常,拋出 ExecutionException 。若當前線程被中斷,拋出 InterruptedException 。 |
3. CompletableFuture 和Future之間的區別與聯系
特性 | Future | CompletableFuture |
---|---|---|
接口/類 | 接口 | 類(實現了 Future 和 CompletionStage 接口) |
異步任務 | 不能直接表示異步任務,只能表示異步任務的結果 | 可以直接表示異步任務并提供豐富的異步編程支持 |
任務完成通知 | 只能通過阻塞的 get 方法或輪詢 isDone 方法檢查任務是否完成 | 提供 thenApply , thenAccept , thenRun 等方法來注冊回調函數,在任務完成時自動執行 |
手動完成 | 不支持手動完成任務 | 提供 complete , completeExceptionally 等方法手動完成任務 |
組合多個任務 | 不支持直接組合多個任務 | 提供 allOf , anyOf 等方法來組合多個任務 |
異常處理 | 只能通過捕獲 ExecutionException 進行異常處理 | 提供 exceptionally , handle , whenComplete 等方法進行異常處理 |
非阻塞獲取結果 | 不支持非阻塞地獲取結果 | 提供 join , getNow , orTimeout , completeOnTimeout 等方法非阻塞地獲取結果或處理超時 |
支持流式 API | 不支持流式 API | 支持流式 API,允許通過鏈式調用編寫更簡潔和可讀的異步代碼 |