欧美1区2区3区激情无套,两个女人互添下身视频在线观看,久久av无码精品人妻系列,久久精品噜噜噜成人,末发育娇小性色xxxx

外賣等實(shí)踐項目問題記錄(1)

ThreadLocal內(nèi)存泄漏問題

最近在復(fù)盤重新黑馬還有尚硅谷一些項目,發(fā)現(xiàn)我們在使用獲取當(dāng)前用戶id這項功能的時候主要是使用ThreadLocal來進(jìn)行存取

定義:

public class BaseContext {

    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }

}

存入:

/**
 * jwt令牌校驗的攔截器
 */
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;
    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判斷當(dāng)前攔截到的是Controller的方法還是其他資源
        if (!(handler instanceof HandlerMethod)) {
            //當(dāng)前攔截到的不是動態(tài)方法,直接放行
            return true;
        }

        //1、從請求頭中獲取令牌
        String token = request.getHeader(jwtProperties.getUserTokenName());

        //2、校驗令牌
        try {
            log.info("jwt校驗:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
            Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
            log.info("當(dāng)前用戶的id:", userId);
            BaseContext.setCurrentId(userId);
            //3、通過,放行
            return true;
        } catch (Exception ex) {
            //4、不通過,響應(yīng)401狀態(tài)碼
            response.setStatus(401);
            return false;
        }
    }
}

獲?。?/strong>

//清空當(dāng)前用戶的購物車數(shù)據(jù)
shoppingCartMapper.deleteByUserId(BaseContext.getCurrentId());

但我們知道ThreadLocal是存在內(nèi)存泄漏問題的

原因分析

ThreadLocal的工作原理 ThreadLocal通過為每個線程維護(hù)一個獨(dú)立的變量副本,實(shí)現(xiàn)了線程間的數(shù)據(jù)隔離。具體來說,ThreadLocal的值存儲在Thread對象的ThreadLocalMap中,鍵是ThreadLocal實(shí)例,值是存儲的數(shù)據(jù)。

內(nèi)存泄漏的可能性

如果ThreadLocal變量沒有被正確清理(調(diào)用remove()方法),即使ThreadLocal實(shí)例本身被回收,ThreadLocalMap中的鍵(弱引用)可能已經(jīng)被回收,但值仍然存在,導(dǎo)致無法釋放內(nèi)存。這種情況尤其容易發(fā)生在使用線程池的場景中,因為線程池中的線程是復(fù)用的,線程的生命周期很長。

我們整個項目里面只用到了存取ThreadLocal中的線程id,卻并沒有在方法結(jié)束后對ThreadLocal進(jìn)行remove這樣會造成一定的風(fēng)險。

如果線程池中的線程被復(fù)用,而ThreadLocal沒有及時清理,可能會導(dǎo)致數(shù)據(jù)污染。例如,前一個請求的用戶ID殘留到了下一個請求中。

解決方案

在本項目中,我們可以修改原本的攔截器,在請求結(jié)束時統(tǒng)一清理ThreadLocal中的數(shù)據(jù)。例如:

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    log.info("請求結(jié)束,執(zhí)行afterCompletion方法...");
    // 在這里編寫請求結(jié)束后的邏輯,例如清理ThreadLocal數(shù)據(jù)
    BaseContext.removeCurrentId(); // 清理當(dāng)前用戶ID
}

使用afterCompletion方法

afterCompletion的作用 afterCompletion方法在請求處理完成(包括視圖渲染)后執(zhí)行,無論請求是否成功或拋出異常。它適合用于清理資源、記錄日志等操作。

不知道我這樣做的是否正確,歡迎各位大佬指教!

#實(shí)習(xí)##蒼穹外賣項目包裝#
全部評論

相關(guān)推薦

04-19 19:33
已編輯
廣州大學(xué) Java
從三月下旬到現(xiàn)在,也有一個月了,我突然發(fā)現(xiàn)過去一個月我似乎什么也沒有做,只有外賣點(diǎn)評,一直****投小廠,也沒有多少回應(yīng)。每天都在想著換項目,一直找一直找,到現(xiàn)在也沒有找到。剛開始打算寫個rpc,跟著慕課網(wǎng)寫了個很簡單沒有任何亮點(diǎn)的rpc,寫完后想著自己去擴(kuò)展,找了幾天的資料,最后又放棄了,覺得要學(xué)的實(shí)在太多了,時間不夠了。后面又想著那我繼續(xù)優(yōu)化外賣點(diǎn)評吧,點(diǎn)評是優(yōu)化了一點(diǎn),但是外賣我真是無從下手。然后我在一本書里面看到了基于netty的即時通訊系統(tǒng),也是比較簡單的那種,但是我跑了一天根本沒跑起來。到網(wǎng)上各種找資料,看到個黑馬聊天室項目,剛開始覺得不錯,跑起來了,也是想著自己擴(kuò)展,雖然我學(xué)過一點(diǎn)點(diǎn)前端,但是我是真的是菜,還有接口定義什么的我真的是無從下手。其實(shí)說白了,就是我總是覺得時間不夠了,不能放那么多時間在項目上了。搞得我總是想著找個差不多的項目然后自己擴(kuò)展,但是由于總是遇到各種問題讓我覺得短時間內(nèi)解決不了,于是就又放棄了??墒聦?shí)上我的這些時間加起來,夠我搞一個項目了,就算沒有搞項目,也夠我背很多八股了。真的煩,本來就雙非0實(shí)習(xí)了。感覺現(xiàn)在的我腦袋空空什么都沒有,心很累,身體也很累,不知道怎么辦好。#簡歷中的項目經(jīng)歷要怎么寫# #你的簡歷改到第幾版了# #最后再改一次簡歷# #如何寫一份好簡歷# #寫簡歷別走彎路# #實(shí)習(xí)工作,你找得還順利嗎?# #雙非能在秋招上岸嗎?#
點(diǎn)贊 評論 收藏
分享
評論
1
4
分享

創(chuàng)作者周榜

更多
牛客網(wǎng)
??推髽I(yè)服務(wù)