본문 바로가기

Java

ThreadLocal - 쓰레드 내에서 변수를 공유하고 싶다면

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