>  기사  >  Java  >  Java의 ThreadLocal에 대한 자세한 소개(코드 예)

Java의 ThreadLocal에 대한 자세한 소개(코드 예)

不言
不言앞으로
2019-03-06 15:56:283308검색

이 기사는 Java의 ThreadLocal에 대한 자세한 소개(코드 예제)를 제공합니다. 이는 특정 참조 가치가 있으므로 도움이 될 수 있습니다.

ThreadLocal은 기본적으로 프로젝트 개발에 사용되지 않지만 면접관은 이런 유형의 질문을 선호하므로 이 클래스의 기능과 원리를 이해하는 것이 필요합니다.

ThreadLocal은 A 클래스입니다. 여러 스레드의 각 스레드에 대해 별도의 변수 복사본을 생성합니다. ThreadLocal을 사용하여 변수를 유지 관리하는 경우 ThreadLocal은 공유 변수에 대한 다중 스레드 작업으로 인한 데이터 불일치를 방지하기 위해 각 스레드에 대해 별도의 변수 복사본을 생성합니다. ThreadLocal 클래스는 어떤 시나리오에서 사용됩니까?

일반적으로

ThreadLocal을 사용하여 문제를 해결하세요.

ThreadLocal 사용 방법

ThreadLocal在实际工业生产中并不常见, 但是在很多框架中使用却能够解决一些框架问题; 比如Spring中的事务、Spring 中 作用域 ScopeRequest的Bean1. ThreadLocal 변수를 사용하여 여러 스레드에서 액세스해야 하는 경우는 다음과 같습니다. 인터넷에서 DBConnectionFactory 클래스를 예로 들어보세요

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnectionFactory {

    private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() {
        @Override
        protected Connection initialValue() {
            try {
                return DriverManager.getConnection("", "", "");
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    };

    public Connection getConnection() {
        return dbConnectionLocal.get();
    }
}

이런 방식으로 클라이언트가 연결을 얻을 때 각 스레드에서 얻은 연결은 해당 스레드에 고유하여 연결의 스레드 격리를 달성하므로 스레드 안전 문제가 없습니다.

ThreadLocal 스레드 격리 구현 방법

1. 현재 스레드의 Connection 개체를 저장하는 역할을 담당하는 Thread 객체에서 주로 ThreadLocalMap 유형의 변수인 threadLocals를 사용하며, 새로 생성된 dbConnectionLocal 변수를 사용합니다. 생성된 Connection 개체는 값으로 사용됩니다. 이 경우 처음 읽을 때 스레드가 존재하지 않으면 ThreadLocal의initialValue 메서드를 호출하여 Connection 개체를 생성하고 반환합니다. 스레드에 대한 변수 복사본은 다음과 같습니다.

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

1. 먼저 현재 스레드 개체 t를 가져온 다음 스레드 t

2에서 ThreadLocalMap의 멤버 속성을 가져옵니다. 초기화(즉, null이 아님)되고 현재 ThreadLocal 객체를 키로 갖는 값이 있으면 현재 스레드(이 예에서는 Connection)에서 얻을 객체를 직접 반환합니다.

3. 스레드가 초기화되었지만(즉, null이 아님) 현재 ThreadLocal 개체를 키로 사용하는 개체가 없으면 Connection 개체를 다시 만들고 이를 threadLocals 맵의 현재 스레드에 추가하고

4를 반환합니다. 현재 스레드의 threadLocals 속성이 초기화되지 않은 경우 ThreadLocalMap 객체를 다시 생성하고 Connection 객체를 생성하여 ThreadLocalMap 객체에 추가하고 반환합니다.

존재하면 바로 반환된다는 것을 이해하기 쉽습니다. 그러면 초기화를 위한 코드는 무엇입니까?

private T setInitialValue() {
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

1. 먼저 위에서 작성한 오버로드된initialValue 메소드를 호출하여 Connection 객체를 생성합니다

2. 현재 스레드의 threadLocal이 비어 있는지 확인합니다. ThreadLocalMap이 초기화된 경우 생성된 객체를 ThreadLocalMap에 직접 추가합니다. 초기화되지 않은 경우 객체를 생성하여 추가합니다.

동시에 ThreadLocal은 직접 작업도 제공합니다. of Thread 객체의 threadLocals 메소드

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

이런 방식으로 우리는initialValue를 구현하지 않고 DBConnectionFactory의 getConnection 메소드에 초기화 작업을 넣을 수 있습니다:

public Connection getConnection() {
    Connection connection = dbConnectionLocal.get();
    if (connection == null) {
        try {
            connection = DriverManager.getConnection("", "", "");
            dbConnectionLocal.set(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return connection;
}

그러면 코드를 읽은 후에 ThreadLocal이 왜 깨달을 수 있는지 명확하게 이해합니다. 많은 변수 스레드가 격리되어 있습니다. 실제로 Map 데이터 구조는 현재 스레드를 캐시하는 데 사용됩니다. 이를 사용하려면 이 스레드의 threadLocals 개체에서 가져옵니다.

물론입니다. , 현재 스레드 아래에서 현재 스레드를 가져옵니다. 스레드의 Map에서 개체를 작동할 때 스레드 동시성 문제는 없습니다. 물론 변수는 스레드 간에 격리될 수 있습니다.

이제 ThreadLocal이 무엇인지, 어떻게 사용하는지 알았습니다. ThreadLocal과 그 기본 구현 원칙이 끝날 수 있을까요? 사실 또 다른 질문이 있습니다. ThreadLocalMap이 무엇이며 왜 이 객체를 사용해야 할까요?

본질적으로 말하면 Map입니다. ThreadLocalMap은 우리가 흔히 보는 맵과 다릅니다.

1. Map 인터페이스를 구현하지 않습니다.

2 이 ThreadLocalMap 메서드는 공용 메서드가 없으며 기껏해야 기본 생성자를 가집니다. ThreadLocal 클래스에서 호출되고 정적 내부 클래스입니다.

3. ThreadLocalMap의 Entry 구현은 WeakReference>

4를 상속합니다. 이 메소드는 Key, Value를 저장하기 위해 Entry 배열만 사용합니다. 링크드 리스트 형식이지만 각 버킷에 항목만 넣으면 됩니다.

위 내용은 Java의 ThreadLocal에 대한 자세한 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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