ThreadLocal

배고픈 징징이 ㅣ 2023. 2. 7. 11:22

1. ThreadLocal 이란?

  • 쓰레드 단위로 로컬 변수를 할당하는 기능
  • 쓰레드 영역에 변수를 설정하기 때문에, 해당 쓰레드가 실행하는 모든 코드에서 그 값을 사용할 수 있다.
  • ThreadLocal에 보관된 데이터는 항상 사용이 끝나면 삭제를해야 한다.
    그렇지 않다면 재사용되는 쓰레드가 올바르지 않은 데이터를 참조할 수 있다
  • ThreadLocal은 메모리 누수의 주범이 될 수 있음으로 주의해서 사용
  • 한 쓰레드에 의해서만 관리가 가능한 로컬변수이기 때문에
    두 쓰레드가 같은 코드를 실행하고 하나의 로컬변수를 참조하더라도 서로의 로컬변수를 볼 수 없다.
  • Thread의 정보를 Key로 하는 Map형식의 데이터를 저장 및 사용하는 자료구조

 

2. 기본 메소드

기본적으로 ThreadLocal은 저장의 set, 호출의 get, 삭제의 remove 3개의 메소드를 주로 사용한다.

추가적으로 withInitial 메소드는 로컬변수 생성과 동시에 원하는 데이터로 초기화해주는 메소드이다.

//TreadLocal 생성
static ThreadLocal<AnyData> threadLocal = new ThreadLocal<>();

//로컬변수 저장
threadLocal.set("Any Data");

//저장된 로컬변수 호출
threadLocal.get();

//저장된 로컬변수 삭제
threadLocal.remove();

//ThreadLocal 생성과 초기화
static ThreadLocal<Integer> threadLocal = new ThreadLocal().withInitial(() -> 7);

 

3. ThreadLocal의 활용

  1. Request에 대해 각각의 쓰레드에서 처리할때
  2. 쓰레드 독립적으로 처리해야하는 데이터 → 인증 처리
  3. 쓰레드에 안전하게 데이터를 보관할때

 

4. 실제 활용 코드

ThreadLocal

public class CallContext {
    static ThreadLocal<CallContext> threadLocal = new ThreadLocal<>();
    User user;

    public static void start() {
        if (threadLocal.get() == null) {
            threadLocal.set(new CallContext());
        }
    }

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

    public static User user() {
        return threadLocal.get().user;
    }

    public static void setUser(User user) {
        threadLocal.get().user = user;
    }
}

 

Filter

@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        ...
        try {
            CallContext.start();

            User user = null;
            if (loginRequired) {
                user = (User) request.getSession().getAttribute("user");
                // 유저를 찾지못했을때
                if (user == null) {
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    return;
                }

                CallContext.setUser(user);
            }
            ...
        } finally {
            CallContext.end();
        }
    }

 

Class

...
pstmt.setString(columns.size() + 2, CallContext.user().userId);
...
반응형

'Java' 카테고리의 다른 글

Static & Singleton Pattern  (0) 2023.02.08
Access Modifier ( 접근 지정자 )  (0) 2023.02.08
Stream  (0) 2023.01.31
@pathvariable  (0) 2023.01.26
VO 데이터 추출  (0) 2023.01.26