【高併發】05 線程封閉 ThreadLocal

一、三種方式

1、Ad-hoc 線程封閉: 程序控制實現,最糟糕

2、堆棧封閉:局部變量、無併發問題

3、ThreadLocal線程封閉:特別好的封閉方法

二、代碼

1、ThreadLocal

package com.current.flame.filter;

/**
 * @author haoxiansheng
 * ThreadLocal 代碼事例
 */
public class RequestHolder {
    private final static ThreadLocal<Long> requestHolder = new ThreadLocal<>();

    public static void  add(Long id) {
        requestHolder.set(id);
    }

    public static Long getId() {
        return requestHolder.get();
    }

    public static void remove() {
        requestHolder.remove();
    }

}

2、controller

package com.current.flame.controller;

import com.current.flame.filter.RequestHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author haoxiansheng
 */
@RestController
@RequestMapping("/threadLocal")
public class ThreadLocalController {

    @GetMapping("/thread")
    public Long threadLoca() {
        return RequestHolder.getId();
    }
}

3、Filter

package com.current.flame.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;


import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author haoxiansheng
 */
@Slf4j
public class HttpFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        log.info("do filter threatId=>{}, path=>{} ",Thread.currentThread().getId(), request.getServletPath());
        RequestHolder.add(Thread.currentThread().getId()); // 添加數據
        filterChain.doFilter(servletRequest, servletResponse);

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}

4、Interceptor

package com.current.flame.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author haoxiansheng
 */
@Slf4j
public class HttpInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("preHandle=>{}",request);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        RequestHolder.remove(); // 移除數據避免內存泄漏
        log.info("afterCompletion=>");
        return;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章