ThreadLocal 이란 무엇인가.
지금 이걸 쓰는 동안에도 잘 이해가 가지 않는다. 최범균님의 블로그중에 ThreadLocal 관한 블로그가 있는데 봐도 잘 모르겠다.
물론 쓰는법은 잘 알겠는데 어디에 써야 될지.. 개발 하다보면 언젠가는 나오겠지
{
int a = 10;
...
// 블록 내에서 a 변수 사용 가능
}
// 변수 a는 위 코드 블록이 끝나면 더 이상 유효하지 않다. (즉, 수명을 다한다.)
반면에 ThreadLocal을 이용하면 쓰레드 영역에 변수를 설정할 수 있기 때문에, 특정 쓰레드가 실행하는 모든 코드에서 그 쓰레드에 설정된 변수 값을 사용할 수 있게 된다.
이런 내용이 있다.
한마디로 말해서 스레드 환경에서 전역 변수는 공유가 되니 로컬변수 인거 마냥 전역변수를 쓰겠다? 이말인가? 대충 이말인거 같다. 내가 이해하기로는..
간단하게 소스를 보자.
public class ThreadLocalTest implements Runnable {
@Data
@AllArgsConstructor
static class UserInfo {
private String name;
}
private static final ThreadLocal<UserInfo> userInfoThreadLocal = new ThreadLocal<UserInfo>() {
@Override
protected UserInfo initialValue() {
return new UserInfo("wonwoo");
}
};
@Override
public void run() {
System.out.println("Thread Name = " + Thread.currentThread().getName() + " default value = " + userInfoThreadLocal.get().getName());
userInfoThreadLocal.set(new UserInfo("kevin"));
System.out.println("Thread Name = " + Thread.currentThread().getName() + " value = " + userInfoThreadLocal.get().getName());
}
public static void main(String[] args) throws InterruptedException {
ThreadLocalTest obj = new ThreadLocalTest();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(obj, "" + i);
t.start();
}
}
}
이 예제가 맞는지도 잘 모르겠다.ㅠㅠ
위의 코드를 보면 ThreadLocal로 선언한 userInfoThreadLocal 변수가 있다. 여기에는 UserInfo라는 객체를 넣어두었다.
결과가 어떻게 될까? 일단 결과 부터 보자.
Thread Name = 1 default value = wonwoo
Thread Name = 2 default value = wonwoo
Thread Name = 2 value = kevin
Thread Name = 4 default value = wonwoo
Thread Name = 5 default value = wonwoo
Thread Name = 5 value = kevin
Thread Name = 3 default value = wonwoo
Thread Name = 3 value = kevin
Thread Name = 0 default value = wonwoo
Thread Name = 4 value = kevin
Thread Name = 1 value = kevin
Thread Name = 9 default value = wonwoo
Thread Name = 8 default value = wonwoo
Thread Name = 6 default value = wonwoo
Thread Name = 7 default value = wonwoo
Thread Name = 9 value = kevin
Thread Name = 7 value = kevin
Thread Name = 6 value = kevin
Thread Name = 8 value = kevin
Thread Name = 0 value = kevin
여기서 보면 스레드는 뒤죽박죽이지만 값은 원하는값(?)이 나온다. default 지정했던 값 wonwoo는 default value로 다 출력이 되고 실행중 바꾼 value는 kevin으로만 다 출력이 되었다. 한마디로 로컬변수 처럼 쓸수 있다는 것인거 같다.
ThreadLocal 사용 예
- 사용자 인증정보 전파 - Spring Security에서는 ThreadLocal을 이용해서 사용자 인증 정보를 전파한다.
- 트랜잭션 컨텍스트 전파 - 트랜잭션 매니저는 트랜잭션 컨텍스트를 전파하는 데 ThreadLocal을 사용한다.
- 쓰레드에 안전해야 하는 데이터 보관
ThreadLocal 주의 사항
쓰레드 풀 환경에서 ThreadLocal을 사용하는 경우 ThreadLocal 변수에 보관된 데이터의 사용이 끝나면 반드시 해당 데이터를 삭제해 주어야 한다. 그렇지 않을 경우 재사용되는 쓰레드가 올바르지 않은 데이터를 참조할 수 있다.
조금더 공부를 해야겠다. 언제 써야 될지도 모르니 더 걱정이다. 딱히 생각나는 부분이 없다.
이것으로 조금이나마 ThreadLocal에 대해 알아봤지만 딱 언제 써야 이게 좋을지는 잘 모르겠다. 천천히 다시 살펴봐야겠다.
참고로 ThreadLocal initialValue 은 아래와 같이 람다를 이용해서 해도 된다.
private static final ThreadLocal<UserInfo> userInfoThreadLocal = ThreadLocal.withInitial(
() -> new UserInfo("wonwoo")
);
참고 :
http://javacan.tistory.com/entry/ThreadLocalUsage