解決ThreadLocal在項目中的線程數據共享問題

目錄

ThreadLocal 簡介

問題描述

為什么會有這個問題

解決方案

1. 使用請求作用域存儲

2. 使用 HTTP Session 存儲

3. 使用 Spring Security

4. 確保 ThreadLocal 的正確使用

5.通常解決方法

結論


在多線程環境中,ThreadLocal 是一種非常有用的工具,它允許我們為每個線程創建一個變量副本。然而,在 Web 應用或服務中,ThreadLocal 有時會導致數據共享問題,特別是在不同線程嘗試訪問相同請求數據的場景中。本文將探討 ThreadLocal 的工作原理,并提供一些解決方案來確保在項目的不同線程中能夠正確獲取數據。

ThreadLocal 簡介

ThreadLocal 是 Java 提供的一個用于創建線程局部變量的類。通過 ThreadLocal,每個線程可以擁有自己的變量副本,這意味著在多線程環境中,每個線程可以獨立地改變自己的副本,而不會影響其他線程中的副本。

問題描述

在 Web 應用中,我們經常需要在不同的請求處理線程之間共享數據。然而,由于 ThreadLocal 的線程局部性,不同線程之間默認是不能共享 ThreadLocal 數據的。這會導致在某些線程中通過 ThreadLocal.get() 獲取到 null 的問題。

為什么會有這個問題

  1. 線程隔離:ThreadLocal的值是線程隔離的,每個線程都有自己的副本
  2. Tomcat線程池:Tomcat使用線程池處理請求,不同的請求可能由不同的線程處理
  3. 生命周期:ThreadLocal的值僅在當前線程的生命周期內有效

解決方案

1. 使用請求作用域存儲

在 Spring 框架中,我們可以使用請求作用域(Request 作用域)來存儲數據,而不是依賴 ThreadLocal。這樣可以確保在同一個請求中可以訪問到之前存儲的數據。

java

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;// 存儲數據
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
attributes.getRequest().setAttribute("user", user);// 獲取數據
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
Users user = (Users) attributes.getRequest().getAttribute("user");

2. 使用 HTTP Session 存儲

如果您需要在多個請求之間保持用戶狀態,可以考慮使用 HTTP Session 來存儲用戶信息。

java

// 存儲數據到 Session
HttpSession session = request.getSession();
session.setAttribute("user", user);// 從 Session 獲取數據
Users user = (Users) session.getAttribute("user");

3. 使用 Spring Security

如果您的應用使用了 Spring Security,那么可以通過 SecurityContextHolder 來獲取認證信息,而不需要手動管理 ThreadLocal

java

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {Users user = (Users) authentication.getPrincipal();
}

4. 確保 ThreadLocal 的正確使用

如果您仍然需要使用 ThreadLocal,確保在請求結束時清除 ThreadLocal 中的數據,以避免內存泄漏,并確保在請求開始時設置數據。

java

// 在請求開始時設置
ThreadLocalUtil.set(user);// 在請求結束時清除
ThreadLocalUtil.remove();

5.通常解決方法

在攔截器中攔截到session的值,再將session值獲取到,設置到ThreadLocal,對于每個http請求,都意味著不同的ThreadLocal,都攔截下來,重新給ThreadLocal賦值

 @Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// 1. 從session獲取用戶信息HttpSession session = request.getSession();Users user = (Users) session.getAttribute("user");// 登錄 URLString loginUrl = request.getContextPath() + "/user/login";// 如果是登錄請求,直接放行if (request.getRequestURI().equals(loginUrl)) {return true;}if (user == null) {throw new LoginException("請登錄!");}// 2. 設置到ThreadLocalThreadLocalUtil.set(user);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 3. 請求結束后清理ThreadLocalUtil.remove();}

攔截器記得在mvc中注冊

結論

ThreadLocal 是一個強大的工具,但在 Web 應用中可能會導致數據共享問題。通過使用請求作用域存儲、HTTP Session 或 Spring Security,我們可以確保在項目的不同線程中能夠正確獲取數據。同時,正確管理 ThreadLocal 的生命周期也是非常重要的,以避免內存泄漏和其他潛在問題。通過這些方法,我們可以充分利用 ThreadLocal 的優勢,同時避免其潛在的陷阱。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62296.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62296.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62296.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

瑞芯微開發板 燒寫固件問題

自用rk3568-firefly-itx-3568q核心板fpga自研底板,因底板所需外設、功能與原廠有較大差異,故裁剪相應sdk,編譯新的內核進行燒寫。然而在更改設備樹過程中kernel/drivers/media/i2c/fpga.c中的像素格式MEDIA_BUS_FMT_YUYV8_2X8誤改成MEDIA_BUS…

photoblog解題過程

本題要求:通過sql注入,找到數據庫中的賬號密碼,并成功登錄。登錄后利用文件上傳,將一句話木馬上傳到數據庫中,然后并對網站進行控制。 解題過程 1、通過在靶機中輸入ifconfig,查到ip為192.168.80.153&…

QT獲取tableview選中的行和列的值

查詢數據庫數據放入tableview(tableView_database)后 QSqlQueryModel* sql_model new QSqlQueryModel(this);sql_model->setQuery("select * from dxxxb_move_lot_tab");sql_model->setHeaderData(0, Qt::Horizontal, tr("id&quo…

「Mac玩轉倉頡內測版46」小學奧數篇9 - 基礎概率計算

本篇將通過 Python 和 Cangjie 雙語實現基礎概率的計算,幫助學生學習如何解決簡單的概率問題,并培養邏輯推理和編程思維。 關鍵詞 小學奧數Python Cangjie概率計算 一、題目描述 假設有一個袋子中有 5 個紅球和 3 個藍球,每次從袋子中隨機…

Face2QR:可根據人臉圖像生成二維碼,還可以掃描,以后個人名片就這樣用了!

今天給大家介紹的是一種專為生成個性化二維碼而設計的新方法Face2QR,可以將美觀、人臉識別和可掃描性完美地融合在一起。 下圖展示為Face2QR 生成的面部圖像(第一行)和二維碼圖像(第二行)。生成的二維碼不僅忠實地保留…

電子商務人工智能指南 1/6 - 搜索、廣告和發現

介紹 81% 的零售業高管表示, AI 至少在其組織中發揮了中等至完全的作用。然而,78% 的受訪零售業高管表示,很難跟上不斷發展的 AI 格局。 近年來,電子商務團隊加快了適應新客戶偏好和創造卓越數字購物體驗的需求。采用 AI 不再是一…

Python快速入門二:Python3 基礎語法

一、編碼 默認情況下,Python 3 源碼文件以 UTF-8 編碼,所有字符串都是 unicode 字符串。 當然你也可以為源碼文件指定不同的編碼: # -*- coding: cp-1252 -*-上述定義允許在源文件中使用 Windows-1252 字符集中的字符編碼,對應適…

nextcloud云盤的部署

借鑒鏈接:https://blog.csdn.net/guigenyi/article/details/126692747 創建自定義 Docker 網絡 docker network create nextcloud-network 創建mysql的賬號密碼都是root 并將其連接到自定義網絡 docker run --name mysql-container --network nextcloud-network -e…

圖(dfs與bfs)算法1

開辟新專題!不擅長的圖它來了來了!(莫名激動 進度:10/100 另:沒想到給自己挖了個坑,可以用dfs的基本上也可以用bfs,看來要雙線并行了。 補:圖算法是我近期得有30%的焦慮來源了&am…

Ruby On Rails 筆記3——表的增刪改查

1.Migration Migrations是一種便利的方法,能以重現的方式隨時間推移改變數據庫schema. 使用Ruby Domain Specific Language (DSL),因此你不用手寫SQL,進而使你的schema和changes與數據庫獨立。 可以把每次migration看作是數據庫的一個新“版本”。A schema開始時什么都沒有…

一、測試工具LoadRunner Professional腳本編寫-錄制前設置

設置基于URL的腳本 原因:基于HTML的腳本會導致login接口不能正確錄制 設置UTF-8 原因:不勾選此項會導致腳本中文變為亂碼

14、鴻蒙學習——管理通知角標

針對未讀的通知,系統提供了角標設置接口,將未讀通知個數顯示在桌面圖標的右上角角標上。 通知增加時,角標上顯示的未讀通知個數需要增加。 通知被查看后,角標上顯示的未讀通知個數需要減少,沒有未讀通知時&#xff0…

Thonny IDE + MicroPython + ESP32 + GY-302 測量環境中的光照強度

GY-302是一款基于BH1750FVI光照強度傳感器芯片的模塊。該模塊能夠直接測量出環境中的光照強度,并將光照強度轉換為數字信號輸出。其具體參數如下表所示。 參數名稱 參數特性 測量范圍 0-65535 LX 測量精度 在環境光下誤差小于20%,能夠自動忽略50/60…

AJAX和XHR、fetch、axios的關系

AJAX中有兩套原生的API,一個是XHR(XMLHttpRequest),一個是Fetch API axios是第三方庫,在瀏覽器環境中使用的是XHR umi-request也是第三方庫,在瀏覽器環境中使用的是Fetch 在 AJAX(Asynchronous JavaScript and XML&am…

openlayers地圖緩存添加

//通過安裝包localforage(npm install localforage)或https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js tileCacheStore.js import localforage from localforage var tileCacheStorenull;// 從緩存中獲取該瓦片 functio…

云軸科技ZStack出席中國電信國際EMCP平臺香港發布會,持續推動海外合作

近日,以“云聚未來 翼起新篇”為主題的中國電信國際多云服務一站式平臺(E-surfing Managed Cloud Platform,簡稱EMCP平臺)新聞發布會在香港成功舉辦,標志著中國電信國際在云計算服務領域取得了又一重大進展。云軸科技…

面試復盤 part 02·1202-1207 日

作品集講述部分 分析反思 作品集講述部分,視覺講述部分需要更換,需要換成其他視覺相關的修改 具體話術 這是一個信息展示優化方案,用戶為財務,信息區分度不足,理解成本較高,因此選擇需要降低理解成本。…

2024.11.29——[HCTF 2018]WarmUp 1

拿到題&#xff0c;發現是一張圖&#xff0c;查看源代碼發現了被注釋掉的提示 <!-- source.php--> step 1 在url傳參看看這個文件&#xff0c;發現了這道題的源碼 step 2 開始審計代碼&#xff0c;分析關鍵函數 //mb_strpos($haystack,$needle,$offset,$encoding):int|…

brpc的二次封裝以及brpc與etcd的聯合

目的&#xff1a; 搭配etcd的注冊中心管理能知道誰能提供什么服務&#xff0c;并用rpc進行服務調用 封裝思想&#xff1a; 信道管理&#xff0c;將不同服務主機的通信信道管理起來 封裝&#xff1a; 1.指定的信道管理類 一個服務通常會有多個節點&#xff0c;每個節點都會…

【提升效率】如何寫好一份詳細設計文檔

版本日期修訂人描述V1.02024/12/6nick huang創建文檔 背景 CSDN在發起“如何做好一份技術文檔”的活動。 想起我最近在寫一份詳細設計&#xff0c;有一些感受&#xff1a; 一份考慮較周全的“詳細設計文檔模板”能起到質量保底的作用。 當一名初級技術人員需要編寫詳細設計文…