ThreadLocal

November 14, 2021

ThreadLocal

java.lang.ThreadLocal은 이름처럼 현재 스레드 내부에서만 사용할 수 있는 로컬 변수를 말한다. 메서드의 구성은 get, set, remove, initialValue 4가지로 사용법은 상당히 직관적이다.

public class ThreadId {
    // Atomic integer containing the next thread ID to be assigned
    private static final AtomicInteger nextId = new AtomicInteger(0);

    // Thread local variable containing each thread's ID
    private static final ThreadLocal<Integer> threadId =
        new ThreadLocal<Integer>() {
            @Override 
            protected Integer initialValue() {
                return nextId.getAndIncrement();
            }
        };

    // Returns the current thread's unique ID, assigning it if necessary
    public static int get() {
        return threadId.get();
    }
}

이처럼 ThreadLocal 인스턴스는 일반적으로 사용자나 트랜잭션의 ID를 스레드에 매핑하기 위한 용도로 많이 사용된다. 예를 들면, 스프링 시큐리티에서의 인증 값 또한 ThreadLocal을 통해 관리된다. 별도로 빈 주입 없이 요청의 시작부터 응답이 나가기 전까지 SecurityContextHolder 객체를 통해 인증 정보를 꺼내 사용할 수 있다.

@Service
public class SampleService {
    public void sample() {
		// 아래와 같이 접근하여 사용 가능
        SecurityContext context = SecurityContextHolder.getContext();
        Authentication authentication = context.getAuthentication();
        String username = authentication.getName();
        Object principal = authentication.getPrincipal();
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
    }
}

ThreadLocal을 직접 생성하여 사용하는 경우 주의해야할 점이 존재한다. Thread Pool 형태로 관리되는 경우에는 작업이 끝나면 remove() 메소드로 리소스를 제거해주는 작업이 꼭 필요하다. 작업이 모두 끝나고 Thread가 완전히 종료되는 것이 아니라 Thread Pool에 의해 재사용되기 때문에, 값이 남아있다면 이 후 작업에서 데이터의 오염이 있을 수 있기 때문이다.


참고


songmk 🙁