인터뷰 질문: ThreadLocal에 대한 이해에 대해 이야기하십시오.

목적

학업 기록, 인터뷰 준비

자원

Station B에서 자주 발생하는 면접 질문에 대한 학습 비디오

핵심 결론

스레드 간 리소스 격리, 스레드 내 리소스 공유.

원칙

각 쓰레드에는 ThreadLocalMap 타입의 멤버변수가 존재하는데 자원객체를 저장하는데 사용된다.
① set()을 호출 즉, ThreadLocal 자신을 키로 자원객체를 값으로 하여 현재 쓰레드 의 ThreadLocalMap 에 저장
② get() 호출, 즉 ThreadLocal 자체를 키로 사용하여 현재 스레드에서 연관된 자원 값 찾기
③ remove() 호출, 즉 ThreadLocal 자체를 키로 사용하여 현재 스레드와 연관된 자원 값 제거

코드 데모

/**
 * TestThreadLocal: 线程之间资源隔离, 线程内资源共享
 *
 * @author xiaozhengN [email protected]
 * @since 2022-11-27 22:12:39
 **/
@Slf4j
public class TestThreadLocal {
    
    
    public static void main(String[] args) {
    
    
        test1();
        test2();
    }

    /**
     * 多个线程调用, 得到的是自己的Connection对象
     */
    private static void test1() {
    
    
        for (int i = 0; i < 5; i++) {
    
    
            new Thread(() -> log.info("当前线程: {}, Connection: {}", Thread.currentThread().getName(), Utils.getConnection()), "test1Thread" + (i + 1)).start();
        }
    }

    /**
     * 一个线程内调用, 得到的是同一个Connection对象
     */
    private static void test2() {
    
    
        for (int i = 0; i < 3; i++) {
    
    
            new Thread(() -> {
    
    
                log.info("当前线程: {}, Connection: {}", Thread.currentThread().getName(), Utils.getConnection());
                log.info("当前线程: {}, Connection: {}", Thread.currentThread().getName(), Utils.getConnection());
            }, "test2Thread" + (i + 1)).start();

        }
    }

    static class Utils {
    
    
        // 线程隔离
        private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

        /**
         * 获取连接
         *
         * @return Connection对象
         */
        public static Connection getConnection() {
    
    
            Connection connection = threadLocal.get();
            if (connection == null) {
    
    
                connection = innerGetConnection();
                threadLocal.set(connection);
            }
            return connection;
        }

        private static Connection innerGetConnection() {
    
    
            try {
    
    
                return DriverManager.getConnection("jdbc:mysql://localhost:3306/bos?useSSL=false", "root", "root");
            } catch (SQLException e) {
    
    
                throw new RuntimeException(e);
            }
        }
    }
}

다른

ThreadLocalMap의 키가 약한 참조로 설계되어야 하는 이유

① 쓰레드는 오랫동안 실행해야 할 수도 있다.(예: 쓰레드 풀의 쓰레드) 키가 더 이상 사용되지 않으면 GC로 재활용해야 한다
.
키 가 null 인지
여부에 따라 값을 해제 메모리를 해제하는 시간은 다음과 같습니다 . , 정적 변수로 사용되므로 GC에서 재활용할 수 없습니다.

참조 리소스

메모리 누수 문제

ThreadLocal 메모리 누수

ThreadLocals 첨자 계산

특수 상수 0x61c88647
0x61c88647

소스 코드 분석

소스 코드 워크

추천

출처blog.csdn.net/xiaozhengN/article/details/128078727