ThreadLocal은 JDK 1.2부터 제공된 오래된 클래스다. 이 클래스를 활용하면 스레드 단위로 로컬 변수를 사용할 수 있기 때문에 마치 전역변수처럼 여러 메서드에서 활용할 수 있다. 다만 잘못 사용하는 경우 큰 부작용(side-effect)이 발생할 수 있기 때문에 다른 스레드와 변수가 공유되지 않도록 주의해야 한다.
Heap 영역은 일반적으로 모든 thread에서 접근 할 수 있지만 stack은 thread 하나당 만들어 지는 메모리 영역으로 thread간 접근이 불가능하다. 따라서일반 변수의 수명은 특정 코드 블록(예, 메서드 범위, for 블록 범위 등) 범위 내에서만 유효하다.
{
int a = 10;
...
// 블록 내에서 a 변수 사용 가능
}
// 변수 a는 위 코드 블록이 끝나면 더 이상 유효하지 않다. (즉, 수명을 다한다.)
동일한 코드를 실행하는 데, 쓰레드1에서 실행할 경우 관련 값이 쓰레드1에 저장되고 쓰레드2에서 실행할 경우 쓰레드2에 저장된다.
public ResponseEx method1(RequestEx request) {
String a = request.a();
String b = request.b();
return new ResponseEx(a, b);
}
a, b에 대해서는 외부에서 접근을 할 수 있는 방법이 없기 때문에 외부 thread에 안전한 변수로 사용할 수 있는 것이다. 그렇기 때문에 변수 공유를 위해서는 파라미터로 받아서 사용해야하며 자신의 변수를 다른 곳에서 사용하게 하기 위해서는 리턴값으로 제공해야하는 단점이 있다.
반면에 ThreadLocal을 이용하면 쓰레드 영역에 변수를 설정할 수 있기 때문에 특정 쓰레드가 실행하는 모든 코드에서 그 쓰레드에 설정된 변수 값을 사용할 수 있게 된다. 아래 그림은 쓰레드 로컬 변수가 어떻게 동작하는 지를 간단하게 보여주고 있다.
ThreadLocal은 한 thread 안에서 파라미터 또는 리턴 값으로 정보를 제공하는 것이 아닌 다른 방법으로 thread 안에서의 값을 공유하는 방법을 제공해준다. 이렇게 Stack 영역에 변수를 선언하는 것에 대해서 단점을 해소할 수 있다.
ThreadLocal의 내부는 thread 정보를 key로 하여 값을 저장해두는 Map 구조를 가지고 있다.
public class ExamService {
public static ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();
public ExamService(Integer value) {
threadLocalValue.set(value);
}
public void threadLocal_1() {
System.out.println("threadLocalValue : " + threadLocalValue.get());
threadLocalValue.remove();
}
}
public class ThreadLocalTest {
@Test
public void threadLocalTest() {
ExamService service = new ExamService(5);
ExamService.threadLocal_1(); // threadLocalValue : 5 출력 확인
}
}
ThreadLocal을 사용할 때 반드시 명심해야 할 부분이 있다. ThreadLocal은 Thead의 정보를 key로 하여 Map의 형식으로 데이터를 저장한 후 사용할 수 있는 자료구조를 가지고 있다. 따라서 만약 ThreadPool을 사용하여 thread를 재활용한다면 동일한 이전에 세팅했던 ThreadLocal의 정보가 남아있어 원치않는 동작을 할 수 있다. 따라서 ThreadPool을 사용하는 경우에는 반드시 모두 사용 후 THreadLocal의 값을 remove 메서드를 사용하여 값을 제거해주는것이 필요하다.
ThreadLocal을 사용하는 일은 실무 입장에서 특히 코어개발에 종종 사용될 것이다. was내 동일 스레드 내의 정보를 이용하여 유용한 기능(사용자 인증정보 전파, 트랜잭션 컨텍스트 전파)등 을 만들거나 쓰레드에 안전 해야햐는 데이터를 보관, 쓰레드 단위로 어떠한 작업이 필요할 때 사용하도록 하자.
'IT' 카테고리의 다른 글
[SpringBoot] 에러 처리 Errorcontroller(@ExceptionHandler) (1) | 2023.08.11 |
---|---|
[Java] MDC를 활용한 로그 추적 (0) | 2023.08.04 |
CQRS ? AbstractRoutingDatasource (0) | 2023.07.29 |
JPA N+1 문제 응용 사례 (2) | 2023.06.17 |
JAVA 불필요한 객체 생성 (1) | 2023.06.11 |