본문 바로가기
Java/Basic

ThreadLocal 이란

by setung 2021. 11. 1.

ThreadLocal은 쓰레드별로 사용할 수 있는 변수 저장 공간이라고 생각하면 된다.

 

간단한 예시를 보자.

@Slf4j
public class NonThreadLocalTest {

    static String data;

    public static void main(String[] args) throws InterruptedException {
        data = "main data";

        Thread thread1 = new Thread(() -> {
            data = "thread1 data";
            log.info(" data={}", data);
        });
        thread1.setName("thread1");

        Thread thread2 = new Thread(() -> {
            data = "thread2 data";
            log.info(" data={}", data);
        });
        thread2.setName("thread2");


        thread1.start();
        thread2.start();
        Thread.sleep(100);

        log.info(" data={}", data);
    }
}

현재 예시에서는 main Thread와 직접 선언한 thread1, threas2 총 3개의 쓰레드가 존재한다.

나의 의도는 전역 변수인 data가 각각 쓰레드에서 main data, thread1 data, thread2 data를 출력이 되는 것이다.

14:34:11.885 [thread2] INFO threadlocal.NonThreadLocalTest - data=thread2 data
14:34:11.885 [thread1] INFO threadlocal.NonThreadLocalTest - data=thread1 data
14:34:11.969 [main] INFO threadlocal.NonThreadLocalTest - data=thread2 data

하지만 결과는 의도와 다르다. main 쓰레드에서 data가 thread2 data가 출력됨을 알 수 있다. 이유는 동시성 이슈인데 여러 쓰레드에서 하나의 공유 자원을 사용하기 때문에 문제가 발생한것이다. 멀티쓰레드 환경에서 공유 자원을 사용할시 데이터를 추적하는 일도 어려우니 주의를 해야한다.

 

 

이번엔 ThreadLocal을 사용해 보겠다.

@Slf4j
public class ThreadLocalTest {

    static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) throws InterruptedException {
        threadLocal.set("main data");

        Thread thread1 = new Thread(() -> {
            threadLocal.set("thread1 data");
            log.info(" data={}", threadLocal.get());
        });
        thread1.setName("thread1");

        Thread thread2 = new Thread(() -> {
            threadLocal.set("thread2 data");
            log.info("data={}", threadLocal.get());
        });
        thread2.setName("thread2");

        thread1.start();
        thread2.start();
        Thread.sleep(100);
        
        log.info("data={}", threadLocal.get());
    }
}

String data 대신 ThreadLocal<String> threadLocal을 넣어 주었다. 

14:41:28.371 [thread2] INFO threadlocal.ThreadLocalTest - data=thread2 data
14:41:28.371 [thread1] INFO threadlocal.ThreadLocalTest -  data=thread1 data
14:41:28.471 [main] INFO threadlocal.ThreadLocalTest - data=main data

결과는 의도하는대로 출력이 되었다. 

 

 

ThreadLocal 사용법은 간단하다. 

get()을 통해 데이터를 불러오고, set()을 통해 데이터를 저장하고, remove()를 통해 데이터를 삭제한다.

ThreadLocal을 사용하는 쓰레드의 기준으로 데이터가 자동으로 다루어 진다.

 

ThreadLocal 사용시 주의사항이 있다.

WAS와 같이 Thread Pool 환경에서는 Thread를 재활용하기 때문에 ThreadLocal에 데이터가 계속 남아있게 된다. 그러므로 remove() 함수를 호출해 데이터를 지워주는게 좋다.                                                                                             

'Java > Basic' 카테고리의 다른 글

Java의 == 와 equals()  (0) 2022.01.14
자바의 Optional 알아보기  (0) 2021.11.09

댓글