출처 : 자바 캔(최범균 선생님) https://javacan.tistory.com/entry/ThreadLocalUsage
일반 변수의 수명은 코드블록 내부에서만 유효하다.
{
int a = 10;
///블록 내부에서 a 사용가능
}
// 자신을 둘러싸고있는 코드블록을 벗어나면, a 의 생명주기는 끝난다.
ThreadLocal 은 쓰레드 영역에 변수를 설정하는 방법이다. 특정 쓰레드가 실행되는 모든 코드에서 그 쓰레드에 설정된 변수 값을 사용할 수 있게 된다.
💫 주목할 점은 Thread1 에서 실행할 경우 값이 Thread1 에 저장되고, Thread2 에서 실행할 경우 값이 Thread2 에 저장된다는 점이다.
ThreadLocal#set()
메소드로 현재 동작하는 쓰레드 영역의 로컬변수에 값을 저장한다.ThreadLocal#get()
메소드로 현재 동작하는 쓰레드 영역의 로컬변수 값을 읽어들인다.ThreadLocal#remove()
메소드로 현재 동작하는 쓰레드 영역의 로컬변수 값을 삭제한다.public class StaticThreadLocal {
public static ThreadLocal<Domain>threadLocalVariable= new ThreadLocal();
}
하나의 Thread 에서 공통적으로 사용할 수 있는 Thread 영역의 로컬변수이므로, a()→b()→c() 로 이어지는 하나의 Thread 상에서 threadLocal 에 저장된 값은 모두 동일하다.
코드의 핵심은 메소드 인자로 Domain 객체를 넘겨주지않아도 같은 Thread 에서 동작하는 코드 간에는 같은 객체를 참조할 수 있다는 것이다.
class A {
public void a() {
String name = Thread.currentThread().getName();
System.out.printf("Thread : %s , ThreadLocal 내부에 값 여부: %s%n",
name, StaticThreadLocal.threadLocalVariable.get());
Domain soomin = new Domain("soomin", 29, name);
StaticThreadLocal.threadLocalVariable.set(soomin);
B b = new B();
b.b();
System.out.printf("\n도메인 객체에 저장된 Thread 이름 : %s %n",
StaticThreadLocal.threadLocalVariable.get().getCurrentThread());
StaticThreadLocal.threadLocalVariable.remove();
}
}
class B {
public void b() {
Domain b = StaticThreadLocal.threadLocalVariable.get();
System.out.printf("b() 함수에서 꺼내온 ThreadLocal 값 : %s%n",domain);
C c = new C();
c.c();
}
}
class C {
public void c() {
Domain domain = StaticThreadLocal.threadLocalVariable.get();
System.out.printf("c() 함수에서 꺼내온 ThreadLocal 값 : %s%n",domain);
}
}
Thread 기준으로 동작하는 코드에 대해서는 ThreadLocal 을 사용하는 것이 유용하다.
public static void main(String[] args) throws InterruptedException {
Thread other = new Thread(() -> new A().a(),"other");
System.out.println("============other 실행=============");
other.start();
Thread.sleep(500);
System.out.println("\n============main 실행=============");
new A().a();
System.out.println("\n============main 에서 다시 실행=============");
new A().a();
}
/*
============other 실행=============
Thread : other , ThreadLocal 내부에 값 여부: null
b() 함수에서 꺼내온 ThreadLocal 값 : Domain{name='soomin', age=29, currentThread='other'}
c() 함수에서 꺼내온 ThreadLocal 값 : Domain{name='soomin', age=29, currentThread='other'}
도메인 객체에 저장된 Thread 이름 : other
============main 실행=============
Thread : main , ThreadLocal 내부에 값 여부: null
b() 함수에서 꺼내온 ThreadLocal 값 : Domain{name='soomin', age=29, currentThread='main'}
c() 함수에서 꺼내온 ThreadLocal 값 : Domain{name='soomin', age=29, currentThread='main'}
도메인 객체에 저장된 Thread 이름 : main
============main 에서 다시 실행=============
Thread : main , ThreadLocal 내부에 값 여부: null
b() 함수에서 꺼내온 ThreadLocal 값 : Domain{name='soomin', age=29, currentThread='main'}
c() 함수에서 꺼내온 ThreadLocal 값 : Domain{name='soomin', age=29, currentThread='main'}
도메인 객체에 저장된 Thread 이름 : main
*/
ThreadLocal#remove()
를 호출하여 데이터를 삭제해야한다.Thread Per Request Model
로 작동하는 Apache Tomcat 같은 애들..