欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot中使用?ThreadLocal?進行多線程上下文管理及注意事項小結(jié)

 更新時間:2025年02月20日 15:03:50   作者:小沈同學(xué)呀  
本文詳細(xì)介紹了ThreadLocal的原理、使用場景和示例代碼,并在SpringBoot中使用ThreadLocal保存請求中攜帶的用戶信息,ThreadLocal通過為每個線程維護獨立的變量副本,解決了線程安全問題,感興趣的朋友一起看看吧

前言

在多線程編程中,線程安全是一個重要的問題。Java 提供了多種機制來處理線程安全問題,其中 ThreadLocal 是一個非常有用的工具。本文將詳細(xì)介紹 ThreadLocal 的原理及其在多線程上下文管理中的應(yīng)用,并在springboot中使用ThreadLocal保存請求中攜帶的用戶信息。

技術(shù)積累

1.什么是 ThreadLocal

ThreadLocal 是 Java 提供的一個類,用于在多線程環(huán)境下為每個線程維護獨立的變量副本。這意味著每個線程都可以獨立地訪問和修改自己的變量副本,而不會影響其他線程的變量。

2. ThreadLocal 的原理

2.1 線程隔離

每個線程都有一個 ThreadLocalMap 對象,該對象存儲了所有 ThreadLocal 變量的副本。ThreadLocalMap 是 Thread 類的一個內(nèi)部類,每個線程實例都有一個 ThreadLocalMap 實例。

2.2 存儲機制

設(shè)置值: 當(dāng)一個線程調(diào)用 ThreadLocal.set(value) 時,ThreadLocal 會將值存儲到當(dāng)前線程的 ThreadLocalMap 中。
獲取值: 調(diào)用 ThreadLocal.get() 時,ThreadLocal 會從當(dāng)前線程的 ThreadLocalMap 中獲取值。

2.3 內(nèi)存管理

弱引用: ThreadLocalMap 使用弱引用(WeakReference)來存儲 ThreadLocal 對象,以防止內(nèi)存泄漏。
清理: 當(dāng) ThreadLocal 對象不再被使用時,它可以被垃圾回收,從而避免內(nèi)存泄漏。

3. 使用場景

3.1 用戶會話管理

在 Web 應(yīng)用中,可以使用 ThreadLocal 存儲用戶會話信息,確保每個請求處理線程都能訪問到正確的會話數(shù)據(jù)。

3.2 事務(wù)上下文管理

在數(shù)據(jù)庫操作中,可以使用 ThreadLocal 存儲事務(wù)上下文,確保每個線程的操作都在正確的事務(wù)中進行。

3.3 線程局部變量

在多線程環(huán)境中,需要每個線程擁有獨立的變量副本時,可以使用 ThreadLocal。

4. 示例代碼

以下是一個簡單的示例,展示了如何使用 ThreadLocal 來管理每個線程的獨立變量。

public class ThreadLocalExample {
// 創(chuàng)建一個 ThreadLocal 實例
private static final ThreadLocal threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
    // 創(chuàng)建多個線程
    for (int i = 0; i < 5; i++) {
        new Thread(() -> {
            // 為每個線程設(shè)置不同的值
            threadLocal.set((int) (Math.random() * 100));
            try {
                // 模擬線程執(zhí)行時間
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 獲取并打印當(dāng)前線程的值
            System.out.println("Thread " + Thread.currentThread().getId() + ": " + threadLocal.get());
            // 清除 ThreadLocal 變量,避免內(nèi)存泄漏
            threadLocal.remove();
        }).start();
    }
}
}

4.1 關(guān)鍵點

線程隔離: 每個線程都有獨立的 ThreadLocal 變量副本。
內(nèi)存管理: 使用 ThreadLocal.remove() 清除不再需要的變量,避免內(nèi)存泄漏。
性能考慮: ThreadLocal 的使用會增加一定的內(nèi)存開銷,因此在不需要時應(yīng)及時清理。

5. 注意事項

5.1 內(nèi)存泄漏

如果不及時清理 ThreadLocal 變量,可能會導(dǎo)致內(nèi)存泄漏。因此,建議在使用完 ThreadLocal 變量后調(diào)用 remove() 方法。

5.2 線程池

在使用線程池時,線程可能會被重用。如果 ThreadLocal 變量沒有被清理,可能會導(dǎo)致后續(xù)任務(wù)訪問到錯誤的數(shù)據(jù)。因此,在使用線程池時,務(wù)必在任務(wù)執(zhí)行完畢后清理 ThreadLocal 變量。

實戰(zhàn)演示

1. User 類

User 類表示用戶數(shù)據(jù)

/**
 * User
 * @author senfel
 * @version 1.0
 * @date 2025/2/18 17:00
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private String id;
    private String username;
}

2. UserContext 類

UserContext 類使用 ThreadLocal 來存儲和刪除用戶數(shù)據(jù)。

/**
 * UserContext
 * @author senfel
 * @version 1.0
 * @date 2025/2/18 17:01
 */
public class UserContext {
    // 創(chuàng)建一個 ThreadLocal 實例來存儲 User 對象
    private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>();
    // 設(shè)置用戶數(shù)據(jù)
    public static void setUser(User user) {
        userThreadLocal.set(user);
    }
    // 獲取用戶數(shù)據(jù)
    public static User getUser() {
        return userThreadLocal.get();
    }
    // 刪除用戶數(shù)據(jù)
    public static void clearUser() {
        userThreadLocal.remove();
    }
}

3.UserInterceptor 類

UserInterceptor 類用于在請求處理前后設(shè)置和清除 ThreadLocal 中的用戶數(shù)據(jù)。

/**
 * UserInterceptor
 * @author senfel
 * @version 1.0
 * @date 2025/2/18 17:03
 */
@Component
public class UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 模擬從請求中獲取用戶數(shù)據(jù)
        String userId = request.getParameter("userId");
        String username = request.getParameter("username");
        if (userId == null || username == null) {
            response.getWriter().write("User ID and Username are required.");
            return false;
        }
        // 創(chuàng)建 User 對象并存儲在 ThreadLocal 中
        User user = new User(userId, username);
        UserContext.setUser(user);
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清除 ThreadLocal 中的用戶數(shù)據(jù),避免內(nèi)存泄漏
        UserContext.clearUser();
    }
}

4.配置攔截器

在 Spring Boot 中配置攔截器,使其在請求處理前后執(zhí)行。

/**
 * WebConfig
 * @author senfel
 * @version 1.0
 * @date 2025/2/18 17:10
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private UserInterceptor userInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(userInterceptor).addPathPatterns("/**");
    }

5.實戰(zhàn)測試

隨便訪問一個路徑,都會從請求中獲取用戶信息并放入local,在執(zhí)行控制器結(jié)束后會清理掉數(shù)據(jù)。

總結(jié)

ThreadLocal 是一個非常強大的工具,可以幫助我們在多線程環(huán)境中管理線程局部變量。通過合理使用 ThreadLocal,可以有效地避免線程安全問題,提高程序的并發(fā)性能和穩(wěn)定性。我們可以在 Spring Boot 應(yīng)用中安全地存儲和管理每個請求的用戶數(shù)據(jù),并通過顯式地清理 ThreadLocal 變量,可以有效避免內(nèi)存泄漏問題。

到此這篇關(guān)于SpringBoot中使用 ThreadLocal 進行多線程上下文管理及其注意事項的文章就介紹到這了,更多相關(guān)SpringBoot ThreadLocal多線程上下文管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解關(guān)于java文件下載文件名亂碼問題解決方案

    詳解關(guān)于java文件下載文件名亂碼問題解決方案

    這篇文章主要介紹了詳解關(guān)于java文件下載文件名亂碼問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • SpringMVC數(shù)據(jù)輸出相關(guān)知識總結(jié)

    SpringMVC數(shù)據(jù)輸出相關(guān)知識總結(jié)

    今天帶大家學(xué)習(xí)SpringMVC的相關(guān)知識,文中對SpringMVC數(shù)據(jù)輸出作了非常詳細(xì)的代碼示例,對正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下
    2021-06-06
  • SpringBoot @Value注解支持配置自動刷新能力擴展方式

    SpringBoot @Value注解支持配置自動刷新能力擴展方式

    本文介紹了如何通過自定義注解和BeanPostProcessor實現(xiàn)SpringBoot中@Value注解的配置自動刷新能力,主要步驟包括:定義一個支持動態(tài)刷新的注解,實現(xiàn)配置的動態(tài)變更,以及通過BeanPostProcessor掃描并刷新使用@Value注解的變量
    2024-12-12
  • SpringBoot之groups應(yīng)對不同的Validation規(guī)則自定義方式

    SpringBoot之groups應(yīng)對不同的Validation規(guī)則自定義方式

    這篇文章主要介紹了SpringBoot之groups應(yīng)對不同的Validation規(guī)則自定義方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java通俗易懂系列設(shè)計模式之適配器模式

    Java通俗易懂系列設(shè)計模式之適配器模式

    這篇文章主要介紹了Java通俗易懂系列設(shè)計模式之適配器模式,對設(shè)計模式感興趣的同學(xué),一定要看一下
    2021-04-04
  • Springboot項目異常處理及返回結(jié)果統(tǒng)一

    Springboot項目異常處理及返回結(jié)果統(tǒng)一

    這篇文章主要介紹了Springboot項目異常處理及返回結(jié)果統(tǒng)一,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • SpringCloud中的Feign服務(wù)間的調(diào)用詳解

    SpringCloud中的Feign服務(wù)間的調(diào)用詳解

    這篇文章主要介紹了SpringCloud中的Feign服務(wù)間的調(diào)用詳解,Feign 是一個聲明式的 REST 客戶端,它能讓 REST 調(diào)用更加簡單,Feign 供了 HTTP 請求的模板,通過編寫簡單的接口和插入注解,就可以定義好 HTTP 請求的參數(shù)、格式、地址等信息,需要的朋友可以參考下
    2024-01-01
  • Mybatis兩種不同批量插入方式的區(qū)別

    Mybatis兩種不同批量插入方式的區(qū)別

    隨著業(yè)務(wù)需要,有時我們需要將數(shù)據(jù)批量添加到數(shù)據(jù)庫,mybatis提供了將list集合循環(huán)添加到數(shù)據(jù)庫的方法,這篇文章主要給大家介紹了關(guān)于Mybatis兩種不同批量插入方式的區(qū)別,需要的朋友可以參考下
    2021-09-09
  • 詳解springboot WebTestClient的使用

    詳解springboot WebTestClient的使用

    WebClient是一個響應(yīng)式客戶端,它提供了RestTemplate的替代方法。這篇文章主要介紹了詳解springboot WebTestClient的使用, 具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • SpringCloud Gateway的路由,過濾器和限流解讀

    SpringCloud Gateway的路由,過濾器和限流解讀

    這篇文章主要介紹了SpringCloud Gateway的路由,過濾器和限流解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論