Thread Local이란 무엇인가?
ThreadLocal은 자바에서 멀티스레딩 프로그래밍을 할 때 사용되는 클래스입니다. 각 스레드가 독립적으로 값을 가지도록 해주며, 여러 스레드가 동시에 같은 변수를 사용할 때 발생할 수 있는 문제를 피할 수 있습니다.
일반적으로 멀티스레딩 환경에서 공유 변수는 동기화가 필요합니다. 하지만 동기화는 성능에 영향을 미칠 수 있습니다. ThreadLocal을 사용하면 스레드마다 고유한 변수를 가질 수 있기 때문에 동기화가 필요 없습니다.
ThreadLocal의 주요 메서드는 다음과 같습니다:
- get(): 현재 스레드의 값을 반환합니다.
- set(T value): 현재 스레드의 값을 설정합니다.
- remove(): 현재 스레드의 값을 삭제합니다.
public class ThreadLocalExample {
// ThreadLocal 변수를 생성합니다.
private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 1);
public static void main(String[] args) {
// 첫 번째 스레드
Thread thread1 = new Thread(() -> {
System.out.println("Thread 1 initial value: " + threadLocalValue.get());
threadLocalValue.set(100);
System.out.println("Thread 1 updated value: " + threadLocalValue.get());
});
// 두 번째 스레드
Thread thread2 = new Thread(() -> {
System.out.println("Thread 2 initial value: " + threadLocalValue.get());
threadLocalValue.set(200);
System.out.println("Thread 2 updated value: " + threadLocalValue.get());
});
// 스레드를 시작합니다.
thread1.start();
thread2.start();
// 메인 스레드에서 값을 확인합니다.
System.out.println("Main thread value: " + threadLocalValue.get());
}
}
- ThreadLocal 변수를 threadLocalValue로 선언하고, 초기값을 1로 설정했습니다.
- 두 개의 스레드를 생성하여 각 스레드에서 threadLocalValue의 값을 출력하고 변경합니다.
- 각 스레드는 자신만의 ThreadLocal 값을 가지므로 서로 영향을 주지 않습니다.
위 내용의 예상 결과 입니다.
Main thread value: 1
Thread 1 initial value: 1
Thread 2 initial value: 1
Thread 1 updated value: 100
Thread 2 updated value: 200
이 예제에서 보시다시피, 각 스레드는 ThreadLocal 변수를 통해 독립적인 값을 가집니다. 메인 스레드, thread1, thread2 모두 자신만의 값을 유지하고 있습니다.
이처럼 ThreadLocal을 사용하면 멀티스레딩 환경에서 동기화 없이도 안전하게 각 스레드가 고유한 상태를 유지할 수 있습니다.
Thread Local의 장점
구분 | 내 |
동기화 불필요 | ThreadLocal을 사용하면 각 스레드가 독립적인 값을 가지기 때문에 동기화(synchronization)가 필요 없습니다. 이는 성능을 향상시키는 데 도움이 됩니다. |
코드 간결성 | 복잡한 동기화 코드 없이도 각 스레드마다 고유한 데이터를 저장하고 접근할 수 있어 코드가 간결해집니다. |
상태 유지 | 각 스레드가 독립적으로 상태를 유지할 수 있습니다. 예를 들어, 데이터베이스 연결이나 세션 정보를 스레드별로 저장할 때 유용합니다. |
재사용 가능 | 재사용이 가능한 객체(예: 포맷터, 데이터베이스 연결 등)를 스레드별로 할당하여 여러 스레드에서 안전하게 사용할 수 있습니다. |
Thread Local 주의할
메모리 누수
ThreadLocal은 강한 참조(strong reference)를 사용하므로, 스레드가 종료된 후에도 ThreadLocal 변수가 참조하는 객체가 해제되지 않으면 메모리 누수가 발생할 수 있습니다. 이를 방지하기 위해 remove() 메서드를 사용하여 스레드가 끝날 때 ThreadLocal 값을 명시적으로 제거해야 합니다.
threadLocalValue.remove();
스레드 풀 사용 시 주의
스레드 풀에서 스레드를 재사용할 때, 이전 작업의 ThreadLocal 값이 다음 작업에 영향을 줄 수 있습니다. 따라서, 작업이 끝날 때마다 ThreadLocal 값을 정리해 주어야 합니다.
복잡성 증가
ThreadLocal을 과도하게 사용하면 코드의 복잡성이 증가할 수 있습니다. 유지보수 및 디버깅이 어려워질 수 있으므로, 꼭 필요한 경우에만 사용해야 합니다.
예기치 않은 동작
ThreadLocal은 각 스레드마다 독립된 값을 가지므로, 값이 예기치 않게 변하지 않는다는 보장이 없습니다. 값을 읽고 쓰는 순서를 명확히 해야 합니다.
다음은 ThreadLocal 사용 후 값을 정리하는 예제입니다
public class ThreadLocalCleanupExample {
private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 1);
public static void main(String[] args) {
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " initial value: " + threadLocalValue.get());
threadLocalValue.set((int) (Math.random() * 100));
System.out.println(Thread.currentThread().getName() + " updated value: " + threadLocalValue.get());
} finally {
// 작업이 끝난 후 ThreadLocal 값을 정리합니다.
threadLocalValue.remove();
}
};
Thread thread1 = new Thread(task, "Thread 1");
Thread thread2 = new Thread(task, "Thread 2");
thread1.start();
thread2.start();
}
}
이 예제에서는 finally 블록에서 threadLocalValue.remove()를 호출하여 스레드가 끝난 후 ThreadLocal 값을 정리합니다. 이렇게 하면 메모리 누수 문제를 방지할 수 있습니다.
'JAVA' 카테고리의 다른 글
[테스트] JaCoCo란 무엇인가? (0) | 2024.07.15 |
---|---|
[TDD] UnitTest(단위 테스트)란 무엇인가? (0) | 2024.07.15 |
[JAVA] JVM GC(Garbage Collection)이란 무엇인가? 대표 알고리즘 알아보기! (0) | 2024.05.26 |
[JAVA] Java 21 Virtual Thread와 Kotlin Coroutine 비교해보기 (0) | 2024.05.23 |
[JAVA] Java 21 새로운 기능 - Virtual Thread란 무엇인가? (0) | 2024.05.23 |