ThreadLocal에서 스레드 풀을 만났을 때

3428 단어
ThreadLocal은 루트 로컬 저장소로 서로 다른 루트 풀의 같은 대상이 get을 호출하여 되돌아오는 것이 다르기 때문에 일부 데이터 루트의 격리를 보장할 수 있습니다.그리고 나는 오늘 이 특수한 대상이 루트 로컬에 저장된 것을 생각했다. 만약에 같은 루트를 복용한다면 얻은 이 대상이 저장한 값도 다른 것입니까?즉, 만약에 스레드 탱크에 부딪히면 일부 스레드 탱크의 스레드를 다시 사용할 수 있는데, 이 대상에 숨겨진 버그가 있습니까?그래서 나는 간단한 테스트를 했다.
public class TestThreadLocal {

    private ThreadLocal local = new ThreadLocal<>(){
        @Override
        protected Integer initialValue() {
            return 1;
        }
    };

    public void getAndAdd() {
        Integer integer = local.get();
        System.out.println(Thread.currentThread().getName() + ": local thread values is:"+integer);
        local.set(integer+1);
    }

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(4);
        final TestThreadLocal testThreadLocal = new TestThreadLocal();

        service.submit(testThreadLocal::getAndAdd);
        service.submit(testThreadLocal::getAndAdd);
        service.submit(testThreadLocal::getAndAdd);
        service.submit(testThreadLocal::getAndAdd);
        service.submit(testThreadLocal::getAndAdd);
    }

}

이 코드는 다음과 같이 인쇄됩니다.
pool-1-thread-1: local thread values is:1
pool-1-thread-3: local thread values is:1
pool-1-thread-1: local thread values is:2
pool-1-thread-4: local thread values is:1
pool-1-thread-2: local thread values is:1

두 번째로 같은 스레드를 사용할 때 이 대상은 더 이상 initialValue가 존재하지 않는다는 것을 설명합니다.
이렇게 하면 많은 상황에서 문제가 있을 것이다. 문제가 있으면 반드시 어떻게 해결해야 하는지를 찾아내야 한다. 이 종류의api를 보고 하나의 방법인remove,remove를 알게 된 후에 다음에 다시 get을 하면 initialValue를 먼저 호출할 것이다. 그래서 코드를 다음과 같이 바꾸면 ok이다.
public class TestThreadLocal {

    private ThreadLocal local = new ThreadLocal<>(){
        @Override
        protected Integer initialValue() {
            return 1;
        }
    };

    public void getAndAdd() {
        Integer integer = local.get();
        System.out.println(Thread.currentThread().getName() + ": (get and add local) thread values is:"+integer);
        local.set(integer+1);
    }

    public void get() {
        System.out.println(Thread.currentThread().getName() + ": (get) local thread values is:"+local.get());
    }

    public void clear() {
        local.remove();
    }

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(4);
        final TestThreadLocal testThreadLocal = new TestThreadLocal();
        Runnable runnable = () -> {
          testThreadLocal.getAndAdd();
          testThreadLocal.get();
          testThreadLocal.clear();
        };
        service.submit(runnable);
        service.submit(runnable);
        service.submit(runnable);
        service.submit(runnable);
        service.submit(runnable);
    }

}

인쇄 결과는 다음과 같습니다.
pool-1-thread-2: (get and add local) thread values is:1
pool-1-thread-1: (get and add local) thread values is:1
pool-1-thread-3: (get and add local) thread values is:1
pool-1-thread-2: (get) local thread values is:2
pool-1-thread-3: (get) local thread values is:2
pool-1-thread-4: (get and add local) thread values is:1
pool-1-thread-1: (get) local thread values is:2
pool-1-thread-2: (get and add local) thread values is:1
pool-1-thread-2: (get) local thread values is:2
pool-1-thread-4: (get) local thread values is:2

좋은 웹페이지 즐겨찾기