ThreadLocal의 사용법과 활용
예전에 스트럿츠2의 아키텍쳐를 공부하던 중에 "액션 컨텍스트가 메소드 호출에 파라미터로서 전달되지 않도록 쓰레드로컬을 구현하고 있으며 -java.lang.ThreadLocal은 자바 1.2에서 추가된 기능이다- 액션 컨텍스트는 각 쓰레드가 객체 자신의 인스턴스를 소유하는 Thread-specific storage를 제공하며 쓰레드 로컬값을 얻기위한 Access 는 쓰레드 로컬값이 어느 곳에서도 다뤄질 수 있도록 하기 위한 정적메소드이다."라고 했던 문구에서 자바1.2 버전부터 지원했다는 쓰레드 로컬이란 이름이 왜 그리 낯설기만 한지 당시엔 기냥 이름 그대로 쓰레드 단위로 로컬변수를 할당하고 사용한다는 의미로만 이해했다.(나중에 알고보니 틀린말은 아니었지만..자바 개발한지 나름 꽤 오래되었다고 생각했는데 용어자체가 낯설게 느껴진다는게 정말 난 날코더인가 하는 생각이 들었던 순간이었다...).
이후로 기냥저냥 코드를 보고 그냥 저냥 그렇게 쓰이는구나라구 넘어가고 그럭저럭 다른 사람에게 이야기할정도로 자주 사용하게 된 기능이지만 자바캔 블로그 에서 로컬쓰레드에 대해서 설명을 한 글이 있기에 올려본다.
(솔직히 능력이 된다면야 ThreadLocal 에 대해 직접 글을 올렸겠지만 올렸다 하더라도 madVirus님처럼 설명할 자신은 정말 없다. -_- .그래서 더더욱 슬프당.흐미~)
쓰레드 단위로 로컬 변수를 할당하는 기능은 ThreadLocal 클래스를 통해서 제공되는데
다음 글에서는 ThreadLocal 클래스의 기본적인 사용방법과 활용 방법을 살펴보도록 한다.
ThreadLocal이란?
일반 변수의 수명은 특정 코드 블록(예, 메서드 범위, for 블록 범위 등) 범위 내에서만 유효하다.
int a = 10;
...
// 블록 내에서 a 변수 사용 가능
}
// 변수 a는 위 코드 블록이 끝나면 더 이상 유효하지 않다. (즉, 수명을 다한다.)
반면에 ThreadLocal을 이용하면 쓰레드 영역에 변수를 설정할 수 있기 때문에, 특정 쓰레드가 실행하는 모든 코드에서 그 쓰레드에 설정된 변수 값을 사용할 수 있게 된다. 아래 그림은 쓰레드 로컬 변수가 어떻게 동작하는 지를 간단하게 보여주고 있다.
ThreadLocal의 기본 사용법
ThreadLocal의 사용방법은 너무 쉽다. 단지 다음의 네 가지만 해 주면 된다.
- ThreadLocal 객체를 생성한다.
- ThreadLocal.set() 메서드를 이용해서 현재 쓰레드의 로컬 변수에 값을 저장한다.
- ThreadLocal.get() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 읽어온다.
- ThreadLocal.remove() 메서드를 이용해서 현재 쓰레드의 로컬 변수 값을 삭제한다.
ThreadLocal<UserInfo> local = new ThreadLocal<UserInfo>();
// 로컬 변수에 값 할당
local.set(currentUser);
// 이후 실행되는 코드는 쓰레드 로컬 변수 값을 사용
UserInfo userInfo = local.get();
public static ThreadLocal<Date> local = new ThreadLocal<Date>();
}
이제 Context 클래스를 사용해서 쓰레드 로컬 변수를 설정하고 사용하는 코드를 작성할 차례이다. 아래는 코드의 예이다.
public void a() {
Context.local.set(new Date());
B b = new B();
b.b();
Context.local.remove();
}
}
class B {
public void b() {
Date date = Context.local.get();
C c = new C();
c.c();
}
}
class C {
public void c() {
Date date = Context.local.get();
}
}
위 코드를 보면 A, B, C 세 개의 클래스가 존재하는데, A.a() 메서드를 호출하면 다음 그림과 같은 순서로 메서드가 실행된다.
위 그림에서 1~10은 모두 하나의 쓰레드에서 실행된다. ThreadLocal과 관련된 부분을 정리하면 다음과 같다.
- 2 - A.a() 메서드에서 현재 쓰레드의 로컬 변수에 Date 객체를 저장한다.
- 4 - B.b() 메서드에서 현재 쓰레드의 로컬 변수에 저장된 Date 객체를 읽어와 사용한다.
- 6 - C.c() 메서드에서 현재 쓰레드의 로컬 변수에 저장된 Date 객체를 읽어와 사용한다.
- 9 - A.a() 메서드에서 현재 쓰레드의 로컬 변수를 삭제한다.
ThreadLocal의 활용
ThreadLocal은 한 쓰레드에서 실행되는 코드가 동일한 객체를 사용할 수 있도록 해 주기 때문에 쓰레드와 관련된 코드에서 파라미터를 사용하지 않고 객체를 전파하기 위한 용도로 주로 사용되며, 주요 용도는 다음과 같다.
- 사용자 인증정보 전파 - Spring Security에서는 ThreadLocal을 이용해서 사용자 인증 정보를 전파한다.
- 트랜잭션 컨텍스트 전파 - 트랜잭션 매니저는 트랜잭션 컨텍스트를 전파하는 데 ThreadLocal을 사용한다.
- 쓰레드에 안전해야 하는 데이터 보관
이 외에도 쓰레드 기준으로 동작해야 하는 기능을 구현할 때 ThreadLocal을 유용하게 사용할 수 있다.
ThreadLocal 사용시 주의 사항
쓰레드 풀 환경에서 ThreadLocal을 사용하는 경우 ThreadLocal 변수에 보관된 데이터의 사용이 끝나면 반드시 해당 데이터를 삭제해 주어야 한다. 그렇지 않을 경우 재사용되는 쓰레드가 올바르지 않은 데이터를 참조할 수 있다.
'개발 이야기 > Java' 카테고리의 다른 글
JOTM을 이용한 분산 트랜잭션 처리 - Spring (0) | 2009.06.15 |
---|---|
Struts2 에서 엑셀로 저장하기(Result를 엑셀로 지정) (0) | 2009.04.22 |
[JavaFX] 웹 서비스 액세스 :학습 곡선 일지 4편 (0) | 2008.09.25 |
[JavaFX] JavaFX 스크립트 함수 : 학습 곡선 일지 3편 (0) | 2008.09.25 |
[JavaFX] 선언적 사용자 인터페이스 : 학습 곡선 일지 2편 (0) | 2008.09.25 |