IT 코딩 JAVAThreadLocalCoding

http://java21.net/blog/osh?post_id=2394

JAVA ThreadLocal에 관하여...

📌 ThreadLocal이란?

ThreadLocal<T>스레드마다 독립적인 값을 저장할 수 있도록 도와주는 클래스입니다.

멀티스레드 환경에서 각 스레드가 개별적으로 데이터를 관리할 수 있도록 하기 때문에, 동기화 없이 안전하게 값을 사용할 수 있습니다.


📌 ThreadLocal의 주요 특징

  1. 스레드마다 독립적인 변수 할당

    • 같은 ThreadLocal 인스턴스를 여러 스레드에서 사용해도, 각 스레드는 자신만의 고유한 값을 갖습니다.

  2. 동기화(synchronized)가 필요 없음

    • 공유 자원이 아니기 때문에, synchronized를 사용하지 않아도 안전하게 값을 관리할 수 있습니다.

  3. 스레드가 종료되면 자동으로 GC(가비지 컬렉션) 대상이 됨

    • 하지만 remove()를 명시적으로 호출하는 것이 좋습니다. (메모리 누수 방지)


📌 사용 방법

java복사편집public class ThreadLocalExample {
    // ThreadLocal 선언 (Integer 타입을 저장)
    private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0);

    public static void main(String[] args) {
        Runnable task = () -> {
            for (int i = 0; i < 3; i++) {
                threadLocalValue.set(threadLocalValue.get() + 1);
                System.out.println(Thread.currentThread().getName() + " - " + threadLocalValue.get());
            }
            threadLocalValue.remove(); // 사용 후 remove() 호출 (메모리 누수 방지)
        };

        // 2개의 스레드 실행
        Thread thread1 = new Thread(task, "Thread-1");
        Thread thread2 = new Thread(task, "Thread-2");

        thread1.start();
        thread2.start();
    }
}

🔹 실행 결과 예시 (스레드마다 독립적인 값 유지)

mathematica복사편집Thread-1 - 1
Thread-1 - 2
Thread-1 - 3
Thread-2 - 1
Thread-2 - 2
Thread-2 - 3

  • Thread-1Thread-2threadLocalValue를 공유하지만, 각각의 값이 독립적으로 증가함.


📌 ThreadLocal을 언제 사용할까?

  1. 스레드마다 개별적으로 관리해야 하는 변수

    • 예: 사용자 인증 정보, 트랜잭션 ID, 로그 컨텍스트 등

  2. 멀티스레드 환경에서 동기화 없이 안전한 데이터 저장이 필요할 때

    • synchronized를 사용하지 않고 스레드별로 변수를 따로 관리할 때 유용함.

  3. DB Connection, Session 등 특정 스레드에서만 유지해야 하는 리소스 관리

    • 예: MyBatis에서 SqlSessionThreadLocal로 관리하는 방식


📌 주의할 점 (메모리 누수 방지)

  1. remove()를 호출해야 함

    • ThreadLocal 값은 스레드가 종료될 때까지 유지되므로, 웹 애플리케이션 같은 환경에서는 스레드 풀(Thread Pool) 사용 시 메모리 누수 문제가 발생할 수 있음.

    • 따라서 작업이 끝난 후 반드시 remove()를 호출해야 함.

  2. 스레드 풀 사용 시 주의

    • ThreadLocal은 스레드가 재사용되면 값이 남아있을 수 있음.

    • 따라서 스레드 풀을 사용할 경우 remove()를 꼭 호출해야 함.