ThreadLocal
쓰레드 단위로 로컬단위를 할당할 수 있는 기능.
로컬 변수는 특정 블럭 (메서드 나 loop 문 등) 내에서 생명주기를 다한다.
하지만 ThreadLocal 은 쓰레드와 생명주기를 함께하는 변수이다.
즉 특정 메서드에서 ThreadLocal 에 값을 저장했더라도, 메서드가 종료된다고 해서 그 값이 사라지는 것이 아니라
쓰레드가 종료될 때까지 해당 값을 호출할 수 있는것이다.
사용법
사용법은 간단하다.
public class Main {
public static void main(String[] args) {
ThreadLocal<String> threadLocal = new ThreadLocal<>();
// 값 저장
threadLocal.set("값")
// 값 불러오기
threadLocal.get() // -- "값"
}
}
어떻게 동작하는지 한번 테스트해보자.
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("initial value"); // -- ThreadLocal 값 세팅
System.out.println(threadLocal.get() + "--" + Thread.currentThread().getName());
Runnable runnable = () -> { // -- 새로운 쓰레드에서 수행할 Runnable
System.out.println(threadLocal.get() + "--" + Thread.currentThread().getName());
threadLocal.set("new value"); //-- ThreadLocal 에 새 값 세팅
System.out.println(threadLocal.get() + "--" + Thread.currentThread().getName());
};
Thread anotherThread = new Thread(runnable, "두번째 쓰레드");
anotherThread.start();
Thread.sleep(3000); // 두번째 쓰레드가 수행되는 시간동안 Stop
System.out.println(threadLocal.get() + "--" + Thread.currentThread().getName());
}
}
결과를 보기전에, 이미 신기한 점이 있다.
외부에 있는 지역변수 처럼 선언한 thradLocal 을 Runnable 익명함수 내에서 호출한 것을 볼 수 있다.
무엇이 신기한지 와닿지 않는다면 아래를 보자.

일반적인 지역변수는 runnable 내에서 호출될 수 없다.
하지만 ThreadLocal은 불러올 수 있었다.
이제 위 테스트를 잊기전에 결과를 확인해보자.
initial value--main
null--두번째 쓰레드
new value--두번째 쓰레드
initial value--main
같은 threadLocal 을 호출했음에도, 새로운 스레드 내에서는 값이 들어가 있지 않았다.
또한 새로운 스레드내에서 값을 다시 할당했지만, 기존 스레드에서 불러온 값은 최초 값 그대로 존재했다.
활용
동작원리와 개념은 이해했다. 그렇다면 이 ThreadLocal을 어떻게 활용할 수 있을까?
일단 단순히 생각해보면, 병렬처리를 할 때 ThreadSafety 한 변수가 필요할때 사용할 수 있을것이다.
물론 자바내의 병렬처리 지원기능들은 모두 크게 고려하지 않아도 ThreadSafety 한 코드를 짜도록 유도되기는 한다..
아니면 웹 어플리케이션에서 단일 쓰레드를 이용하는 요청에 대하여 고유한 로그값을 주거나 하는데 사용할 수 있을 것 같다.
썩 유용한 활용도가 떠오르지 않는다. 그래서 그냥 활용되고 있는 상용 예제를 찾아보았다.
Spring Security 의 SecurityContextHolder 에서 UserDetails 와 같은 인증 정보를 전파하는데 사용한다고한다.

주의점
마지막으로, ThreadLocal 을 사용할때에는 항상 사용 후 값을 초기화 해주어야한다.
쓰레드가 쓰레드 풀로 돌아갔다가 재 사용될 때, 원하지 않는 값을 불러와 장애가 발생할 수 있다.
'Java' 카테고리의 다른 글
| 부동소수점과 BigDecimal (0) | 2022.03.18 |
|---|---|
| DynamicProxy & CGLib (0) | 2022.02.20 |