Java/일반

ThreadLocal

창욱씨 2020. 5. 26. 21:50

 일반 변수의 수명은 특정 코드 블록 범위 내에서만 유효합니다.

{
    int a = 10;
    // 변수 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();
    }
  }
}

 위의 예제를 실행해 보면 아래와 비슷하게 출력되는 것을 볼 수 있습니다.

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

 이를 보면 스레드는 뒤죽박죽이지만 모든 스레드 name의 시작 값은 각자 wonwoo로 시작해서 kevin으로 끝나는 것을 볼 수 있습니다. 이처럼 각 스레드가 수행하는 스레드 내의 모든 영역에서 사용할 수 있도록 변수를 설정하도록 만들어주는 것이 ThreadLocal입니다.

ThreadLocal의 활용

  • 사용자 인증 정보 전파: Spring Security에서는 ThreadLocal을 이용해서 사용자 인증 정보를 전파합니다.
  • 트랜잭션 컨텍스트 전파: 트랜잭션 매니저는 트랜잭션 컨텍스트를 전파하는데 ThreadLocal을 사용합니다.
  • 스레드에 안전해야 하는 데이터 보관

ThreadLocal 사용시 주의사항

 ThreadLocal 변수에 보관된 데이터의 사용이 끝나면 반드시 해당 데이터를 삭제해 주어야 합니다. 그렇지 않을 경우, 재사용되는 스레드가 올바르지 않은 데이터를 참조할 수 있습니다.

728x90