>  기사  >  Java  >  Java에서 ThreadLocal 스레드 변수의 구현 원리는 무엇입니까?

Java에서 ThreadLocal 스레드 변수의 구현 원리는 무엇입니까?

PHPz
PHPz앞으로
2023-05-16 21:07:10519검색

ThreadLocal이란 무엇입니까?

ThreadLocal을 사용하면 스레드 전용 변수를 만들 수 있습니다. 이 변수는 다른 스레드에 표시되지 않습니다. ThreadLocal은 각 스레드에서 변수의 복사본을 생성하고 각 스레드는 코드 예제인 전용 스레드 변수에 액세스할 수 있습니다.

public class ThreadLocalDemo {
 
    //创建一个ThreadLocal对象,用来为每个线程会复制保存一份变量,实现线程封闭
    private  static ThreadLocal<Integer> localNum = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 1;
        }
    };
 
    public static void main(String[] args) {
          //线程0
          new Thread(){
              @Override
              public void run() {
                   localNum.set(1);
                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  localNum.set(localNum.get()+10);
                  System.out.println(Thread.currentThread().getName()+":"+localNum.get());//11
              }
          }.start();
        //线程1
        new Thread(){
            @Override
            public void run() {
                localNum.set(3);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                localNum.set(localNum.get()+20);
                System.out.println(Thread.currentThread().getName()+":"+localNum.get());//23
            }
        }.start();
        
        System.out.println(Thread.currentThread().getName()+":"+localNum.get());//0
    }
}

위에서 언급한 것처럼 메인 스레드와 새로 생성된 2개의 스레드를 합하면 총 3개의 스레드가 있습니다. 각 스레드에는 자체 전용 변수 1, set() 및 get(이 포함되어 있습니다. ) 메소드를 사용하여 값을 설정하고 가져옵니다. 실행 결과는 다음과 같습니다.

Java에서 ThreadLocal 스레드 변수의 구현 원리는 무엇입니까?

ThreadLocal 구현 원리 분석

ThreadLocal은 모든 유형의 객체를 허용하고 내부적으로 ThreadLocalMap을 유지 관리하는 일반 클래스입니다. 우리가 사용하는 get(), set() 등은 실제로 이 클래스에서 나옵니다. 개인 값을 기록하기 위해 현재 스레드에 대해 ThreadLocalMap 개체가 생성될 때마다

Java에서 ThreadLocal 스레드 변수의 구현 원리는 무엇입니까?

set() 메서드를 먼저 살펴보겠습니다.

public void set(T value) {
    //拿到当前线程
    Thread t = Thread.currentThread();
    //拿到当前线程map
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //存在设置值
        map.set(this, value);
    else
        //不存在则创建
        createMap(t, value); 
}
void createMap(Thread t, T firstValue) {
    //threadLocals属性即为此map
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

그러면 get() 메소드

public T get() {
    //拿到当前线程
    Thread t = Thread.currentThread();
    //拿到当前线程对应的map
    ThreadLocalMap map = getMap(t);
    //如果已有map
    if (map != null) {
        //取值操作, 拿到对应的Entry
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
           @SuppressWarnings("unchecked")
           T result = (T)e.value;
           return result;
        }
    }
    //没有map, 则去创建初始化一个map
    return setInitialValue();
}
private T setInitialValue() {
    //initialValue()方法返回的value为null
    T value = initialValue();
    //拿到当前线程去创建对应的map
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

ThreadLocal은 ThreadLocalMap의 패키지로 이해될 수 있습니다

ThreadLocal 메모리 누수 문제

ThreadLocalMap에서 ThreadLocal 객체는 약한 참조를 키로 사용합니다

Java에서 ThreadLocal 스레드 변수의 구현 원리는 무엇입니까?

이 경우 ThreadLocal cal 외부의 강력한 참조가 없으면 키는 GC에 의해 재활용될 예정이므로 ThreadLocalMap의 키는 null이 되고 값은 여전히 ​​강력한 참조 체인을 갖습니다.

스레드는 동시에 여러 ThreadLocal을 가질 수 있습니다. 약한 참조인 키가 재활용되면 그 값은 재활용될 수 없으므로 이 ThreadLocal의 수명 주기는 이 스레드만큼 길어지게 됩니다(이 값의 강한 참조 체인은 깨지지 않기 때문입니다). 스레드가 실행을 완료할 때까지) 스레드가 종료되지 않으면 누적된 값도 재활용할 수 없으므로 메모리 누수 문제가 발생합니다

여기서 문제를 해결하는 방법은: 제거() 메서드를 호출하는 것입니다. ThreadLocal을 사용한 후 매번 데이터를 삭제하려면

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
       m.remove(this);
}

키의 장단점을 살펴보겠습니다. 참조의 차이점

키를 강력한 참조로 사용하는 경우 키의 수명 주기는 스레드만큼 깁니다. 안정적인 강력한 참조 체인이 있어 재활용할 수 없으므로 약한 참조로 사용되면 GC가 자동으로 재활용하므로 후속 Remove() 메서드에서 더 나은 재활용 가치를 얻을 수 있으므로 일반적으로 설계합니다. ThreadLocal은 비공개 정적이어야 하며, 사용 후 제거() 메서드를 사용하여 수동으로 삭제하세요

위 내용은 Java에서 ThreadLocal 스레드 변수의 구현 원리는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제