문제

을 사용해야 하는 경우에는 ThreadLocal 변?

어떻게 사용됩니까?

도움이 되었습니까?

해결책

가능한 (그리고 일반적인) 사용은 스레드 안전이 아닌 객체가있을 때입니다. 동기화 그 물건에 대한 접근 (나는 당신을보고 있습니다. SimpledateFormat). 대신, 각 스레드에 자체 인스턴스를 객체의 인스턴스를 제공하십시오.

예를 들어:

public class Foo
{
    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };

    public String formatIt(Date date)
    {
        return formatter.get().format(date);
    }
}

선적 서류 비치.

다른 팁

a ThreadLocal 주어진 내에서 데이터에 대한 참조입니다 Thread, 당신은 사용할 때 클래스로드 누출로 끝날 수 있습니다. ThreadLocal스레드 풀을 사용하는 애플리케이션 서버의 s. 청소에 대해 매우 조심해야합니다. ThreadLocal당신 get() 또는 set() 사용함으로써 ThreadLocal'에스 remove() 방법.

완료되면 정리하지 않으면 배포 된 WebApp의 일부로로드 된 클래스에 대한 참조가 영구 힙 그리고 쓰레기를 수집하지 않을 것입니다. WebApp을 재배치/배포하지 않으면 각각 정리되지 않습니다. ThreadWebapp의 클래스에 대한 참조는 Thread 귀하의 WebApp이 소유 한 것이 아닙니다. 각 연속 배치는 수집되지 않는 새로운 클래스 인스턴스를 생성합니다.

당신은 java.lang.OutOfMemoryError: PermGen space 그리고 일부 인터넷 검색 후에는 아마도 증가 할 것입니다 -XX:MaxPermSize 버그를 고치는 대신.

이러한 문제가 발생하면 사용하여 어떤 스레드와 클래스 가이 참조를 유지하는지 결정할 수 있습니다. Eclipse의 메모리 분석기 및/또는 다음에 의해 Frank Kieviet의 가이드 그리고 후속 조치.

업데이트 : 다시 발견되었습니다 Alex Vasseur의 블로그 항목 그것은 내가 일부를 추적하는 데 도움이되었습니다 ThreadLocal 내가 가지고 있던 문제.

많은 프레임 워크는 ThreadLocals를 사용하여 현재 스레드와 관련된 컨텍스트를 유지합니다. 예를 들어 현재 트랜잭션이 ThreadLocal에 저장되면 모든 메소드 호출을 통해 매개 변수로 전달할 필요가 없습니다. 웹 응용 프로그램은 현재 요청 및 세션에 대한 정보를 ThreadLocal에 저장하여 응용 프로그램에 쉽게 액세스 할 수 있도록 할 수 있습니다. Guice를 사용하면 구현할 때 ThreadLocals를 사용할 수 있습니다 커스텀 스코프 주입 된 물체의 경우 (Guice의 기본값 서블릿 스코프 아마도 아마도 그것들을 사용합니다).

ThreadLocals는 한 종류의 글로벌 변수입니다 (하나의 스레드로 제한되어 있기 때문에 약간 덜 악) 따라서 원치 않는 부작용 및 메모리 누출을 피하기 위해 사용할 때주의해야합니다. API를 설계하여 더 이상 필요하지 않은 경우 ThreadLocal 값이 항상 자동으로 지우고 API의 잘못된 사용이 불가능하지 않도록 설계하십시오 (예 : 이와 같이). Threadlocals는 코드를 클리너로 만드는 데 사용될 수 있으며, 드문 경우에는 무언가를 만들 수있는 유일한 방법입니다 (내 현재 프로젝트는 두 가지 경우가 있었으며 문서화되어 있습니다. 여기 "정적 필드 및 글로벌 변수").

Java에서는 스레드마다 변할 수있는 데이텀이있는 경우, 선택은 해당 데이텀을 필요로하는 모든 방법으로 전달하거나 데콜을 스레드와 연결해야합니다. 모든 방법이 이미 공통 "컨텍스트"변수를 전달 해야하는 경우 모든 곳에서 데이텀을 전달하는 것이 실행 가능할 수 있습니다.

그렇지 않은 경우 추가 매개 변수로 메소드 서명을 혼란스럽게 만들고 싶지 않을 수 있습니다. 비 스레드 세계에서는 전역 변수와 동등한 Java의 문제를 해결할 수 있습니다. 나사산 단어에서, 글로벌 변수와 동등한 것은 스레드-로컬 변수이다.

책에는 아주 좋은 예가 있습니다 실제로 Java 동시성. 저자 (Where Author)조슈아 블로 치) 스레드 감금이 스레드 안전성을 달성하는 가장 간단한 방법 중 하나 인 방법을 설명합니다. ThreadLocal 스레드 감금을 유지하는보다 공식적인 수단입니다. 결국 그는 또한 사람들이 글로벌 변수로 사용하여 사람들이 어떻게 남용 할 수 있는지 설명합니다.

언급 된 책에서 텍스트를 복사했지만 Code 3.10은 ThreadLocal을 어디에 사용 해야하는지 이해하는 것이 그리 중요하지 않기 때문에 누락되었습니다.

스레드-로컬 변수는 종종 변이 가능한 싱글 톤 또는 글로벌 변수를 기반으로 설계에서 공유하는 것을 방지하는 데 사용됩니다. 예를 들어, 단일 스레드 애플리케이션은 모든 방법에 연결을 전달하지 않도록 시작시 초기화 된 글로벌 데이터베이스 연결을 유지할 수 있습니다. JDBC 연결은 스레드-안전이 아닐 수 있으므로 추가 조정없이 전역 연결을 사용하는 멀티 스레드 애플리케이션도 스레드 안전이 아닙니다. Listing 3.10의 Connectholder에서와 같이 JDBC 연결을 저장하기 위해 ThreadLocal을 사용하면 각 스레드가 자체 연결됩니다.

ThreadLocal은 응용 프로그램 프레임 워크 구현에 널리 사용됩니다. 예를 들어, J2EE 컨테이너는 트랜잭션 컨텍스트를 EJB 호출 기간 동안 실행 스레드와 연관시킵니다. 이는 트랜잭션 컨텍스트를 보유하는 정적 스레드 로컬을 사용하여 쉽게 구현됩니다. 프레임 워크 코드가 현재 실행중인 트랜잭션을 결정해야 할 때이 ThreadLocal에서 트랜잭션 컨텍스트를 가져옵니다. 이는 실행 컨텍스트 정보를 모든 방법으로 전달해야 할 필요성을 줄이지만이 메커니즘을 프레임 워크에 사용하는 모든 코드를 연결한다는 점에서 편리합니다.

스레드 제한 속성을 글로벌 변수를 사용하거나 "숨겨진"메소드 인수를 생성하는 수단으로 취급하여 Threadlocal을 남용하기 쉽습니다. 글로벌 변수와 마찬가지로 스레드-로컬 변수는 재사용 성을 떨어 뜨리고 클래스간에 숨겨진 커플 링을 도입 할 수 있으므로주의해서 사용해야합니다.

본질적으로, 필요할 때 변수의 값은 현재 스레드에 의존합니다 그리고 그것 다른 방식으로 스레드에 값을 첨부하는 것이 편리하지 않습니다. (예 : 서브 클래스 스레드).

일반적인 경우는 어디에 있습니다 다른 프레임 워크가 스레드를 만들었습니다 코드가 실행중인 경우, 예를 들어 서블릿 컨테이너가 있거나, 변수가 "논리적 위치에 있으므로"(스레드 서브 클래스 또는 다른 해시 맵에 매달려있는 가변이 아닌)이기 때문에 ThreadLocal을 사용하는 것이 더 합리적입니다). .

내 웹 사이트에는 좀 더 있습니다 ThreadLocal을 사용하는시기의 토론 및 예 그것은 또한 관심이있을 수 있습니다.

일부 사람들은 스레드 번호가 필요한 특정 동시 알고리즘에서 각 스레드에 "스레드 ID"를 첨부하는 방법으로 ThreadLocal을 사용합니다 (예 : Herlihy & Shavit 참조). 그러한 경우, 당신이 정말로 혜택을 받고 있는지 확인하십시오!

문서 [스레드-로컬 변수]에 액세스하는 각 스레드 (get 또는 set 메소드를 통해) 자체, 독립적으로 초기화 된 변수 사본이 있습니다."

각 스레드에 자체 사본이 있어야 할 때 하나를 사용합니다. 기본적으로 데이터는 스레드간에 공유됩니다.

WebApp 서버는 스레드 풀을 유지할 수 있으며 ThreadLocal 클라이언트에 대한 응답 전에 VAR을 제거해야하므로 다음 요청에 의해 현재 스레드가 재사용 될 수 있습니다.

  1. Java의 ThreadLocal은 JDK 1.2에 도입되었지만 나중에 JDK 1.5에서 STREBRECAL 변수에 유형 안전을 도입하기 위해 생성되었습니다.

  2. ThreadLocal은 스레드 범위와 연결될 수 있으며 스레드가 실행하는 모든 코드는 ThreadLocal 변수에 액세스 할 수 있지만 두 개의 스레드는 서로를 볼 수 없습니다.

  3. 각 스레드는 Threadlocal 변수의 독점 사본을 보유하고 있으며, 이는 스레드가 다른 실시간 참조가 없기 때문에 스레드가 완성되거나 죽은 후 정상적으로 또는 예외로 인해 쓰레기 수집을받을 수 있습니다.

  4. Java의 ThreadLocal 변수는 일반적으로 클래스의 개인 정적 필드이며 스레드 내부에서 상태를 유지합니다.

더 읽기 : Java의 ThreadLocal- 예제 프로그램 및 튜토리얼

두 사용하는 경우 threadlocal 변수를 사용할 수 있습니다-
1-할 때 우리는 할 요구 사항과 연결 상태를 스레드에(예를 들어,사용자 ID 또는 트랜잭션 ID).는 일반적으로 발생하는 웹 응용 프로그램과 모든 요청을 서블릿 고유한 transactionID 연결되어 있습니다.

// This class will provide a thread local variable which
// will provide a unique ID for each thread
class ThreadId {
    // Atomic integer containing the next thread ID to be assigned
    private static final AtomicInteger nextId = new AtomicInteger(0);

    // Thread local variable containing each thread's ID
    private static final ThreadLocal<Integer> threadId =
        ThreadLocal.<Integer>withInitial(()-> {return nextId.getAndIncrement();});

    // Returns the current thread's unique ID, assigning it if necessary
    public static int get() {
        return threadId.get();
    }
}

참고로 여기는 방법 withInitial 를 사용하여 구현 lambda expression.
2-다른 사용하는 경우 우리가 원하는 스레드에 안전한 인스턴스는 우리가 사용하고 싶지 않은 동기화로 사용하면 성능과 동기화가 더 있습니다.하나 이러한 경우는 경우 simpledateformat 의 사용됩니다.이후 simpledateformat 의지 않는 스레드에 안전하다 그래서 우리가 제공하는 메커니즘을 확인 그것은 스레드에 안전합니다.

public class ThreadLocalDemo1 implements Runnable {
    // threadlocal variable is created
    private static final ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue(){
            System.out.println("Initializing SimpleDateFormat for - " + Thread.currentThread().getName() );
            return new SimpleDateFormat("dd/MM/yyyy");
        }
    };

    public static void main(String[] args) {
        ThreadLocalDemo1 td = new ThreadLocalDemo1();
        // Two threads are created
        Thread t1 = new Thread(td, "Thread-1");
        Thread t2 = new Thread(td, "Thread-2");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        System.out.println("Thread run execution started for " + Thread.currentThread().getName());
        System.out.println("Date formatter pattern is  " + dateFormat.get().toPattern());
        System.out.println("Formatted date is " + dateFormat.get().format(new Date()));
    } 

}

Java 8 릴리스 이후 초기화하는 선언적 방법이 더 있습니다. ThreadLocal:

ThreadLocal<Cipher> local = ThreadLocal.withInitial(() -> "init value");

Java 8이 출시 될 때까지 다음을 수행해야했습니다.

ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};

또한, 인스턴스화 방법 (생성자, 공장 방법)이 사용되는 클래스의 경우 ThreadLocal 매개 변수를 사용하지 않으므로 간단히 메소드 참조를 사용할 수 있습니다 (Java 8에 소개).

class NotThreadSafe {
    // no parameters
    public NotThreadSafe(){}
}

ThreadLocal<NotThreadSafe> container = ThreadLocal.withInitial(NotThreadSafe::new);

메모:당신이 지나가고 있기 때문에 평가는 게으르다 java.util.function.Supplier 람다는 때에 만 평가됩니다 ThreadLocal#get 호출되지만 값은 이전에 평가되지 않았습니다.

Threadlocal 패턴에 매우주의해야합니다. Phil이 언급 한 것과 같은 일부 주요 측면이 있지만, 언급되지 않은 것은 Threadlocal 컨텍스트를 설정하는 코드가 "재진입"되지 않도록하는 것입니다.

정보를 설정하는 코드가 두 번째 또는 세 번째로 실행될 때 나쁜 일이 발생할 수 있습니다. 예상하지 못했을 때 스레드에 대한 정보가 돌연변이되기 시작할 수 있기 때문입니다. 따라서 다시 설정하기 전에 ThreadLocal 정보가 설정되지 않았는지주의하십시오.

언제?

객체가 스레드-안전이 아닌 경우, 확장 성을 방해하는 동기화 대신 모든 스레드에 하나의 객체를 제공하고 스레드 로컬 인 스레드 범위를 유지하십시오. 가장 자주 사용되지만 스레드 안전 객체 중 하나는 데이터베이스 연결 및 JMSConnection입니다.

어떻게 ?

한 가지 예는 Spring Framework가 Threadlocal 변수에 이러한 연결 객체를 유지하여 무대 뒤에서 트랜잭션을 관리하기 위해 SloodLocal을 많이 사용하는 것입니다. 높은 수준에서 트랜잭션이 시작되면 연결을 받고 (자동 커밋을 비활성화하고) ThreadLocal에 보관합니다. 추가 DB 호출에서 동일한 연결을 사용하여 DB와 통신합니다. 결국, ThreadLocal에서 연결을 취하고 거래를 커밋 (또는 롤백)하고 연결을 공개합니다.

Log4J는 또한 MDC를 유지하기 위해 ThreadLocal을 사용한다고 생각합니다.

ThreadLocal 유용하고 싶을 때는,어떤 상태로 공유하지 않아야 하는 사이에 다른 스레드가 있지만,그것은에 액세스할 수 있어야에서 각 스레드하는 동안 그것의 전체 수명이다.

예를 들어,상상 웹 응용 프로그램,각 요청에 의해 제공되는 다른 스레드가 있습니다.상상하는 각 요청에 대해 필요한 조각의 데이터를 여러 번는 꽤 비싼하여 계산합니다.그러나,데이터 변경되었을 수 있는 각 들어오는 요청을 의미하는,사용할 수 없습니다 일반 캐시입니다.간단한,빠른 이 문제에 대한 해결책하는 것입 ThreadLocal 변수를 잡고 접근하이 데이터를 가지고,그래서 당신이 계산하는 그것에 대해 한 번만 각각의 요청을 합니다.물론,이 문제가 될 수 있습니다 해결을 사용하지 않고 ThreadLocal, 지만,나는 그것을 고안에 대한 그림 그 목적이다.

는 말했다,해야 하는 마음에 ThreadLocals 는 기본적으로 형태의 글로벌 상태입니다.결과적으로,그것은 많은 다른 의미에만 사용해야 합니다 고려한 후 다른 모든 가능한 솔루션을 제공합니다.

여기에 정말 새로운 것은 없지만 오늘은 ThreadLocal 웹 응용 프로그램에서 Bean 검증을 사용할 때 매우 유용합니다. 유효성 검사 메시지는 현지화되었지만 기본적으로 사용됩니다 Locale.getDefault(). 구성 할 수 있습니다 Validator 다른 MessageInterpolator, 그러나 지정할 방법이 없습니다 Locale 전화 할 때 validate. 그래서 당신은 정적을 만들 수 있습니다 ThreadLocal<Locale> (또는 더 나은 방법은 다른 것들이있는 일반 컨테이너입니다. ThreadLocal 그리고 당신의 관습을 갖습니다 MessageInterpolator 선택 Locale 그것을 통해서. 다음 단계는 a를 작성하는 것입니다 ServletFilter 세션 값을 사용하거나 사용합니다 request.getLocale() 로케일을 골라 보관하려면 ThreadLocal 참조.

@unkNown (Google)에서 언급했듯이, 사용은 참조 된 값이 각 스레드에서 고유 할 수있는 전역 변수를 정의하는 것입니다. 사용법은 일반적으로 현재 실행 스레드와 연결된 일종의 맥락 정보를 저장하는 것을 수반합니다.

우리는 Java EE 환경에서이를 사용하여 사용자 ID를 Java EE 인식이 아닌 클래스에 전달합니다 (httpsession 또는 EJB SessionContext에 액세스 할 수 없습니다). 이런 식으로 보안 기반 운영을 위해 신원을 사용하는 코드는 모든 방법 호출에서 명시 적으로 통과하지 않고도 어디에서나 신원에 액세스 할 수 있습니다.

대부분의 Java EE 호출에서 운영의 요청/응답주기는이 유형의 사용법이 잘 정의 된 입력 및 종료 지점을 STREWLLOCAL을 설정하고 설정하지 않기 때문에 쉽게 사용합니다.

Threadlocal은 비 동기화 된 방법의 여러 스레드에 의해 변이 가능한 객체에 액세스하는 것이 동기화되도록합니다.

이것은 각 스레드에 대한 새로운 인스턴스를 조정하여이를 바르면 달성됩니다. 따라서 각 스레드에 대한 로컬 사본입니다. 이것은 로컬 변수처럼 액세스 할 수있는 메소드에서 인스턴스 변수를 만들기위한 해킹입니다. 아시를 알 수 있듯이 로컬 변수는 스레드에서만 사용할 수 있습니다. 한 가지 차이점은 다음과 같습니다. 메소드 변수는 스레드에서 사용할 수 없습니다. 메서드 실행이 끝나면 스레드 로컬과 공유하는 객체가 정리 될 때까지 여러 메소드에서 사용할 수있는 곳이 끝나면 스레드에서 사용할 수 없습니다.

정의에 따라 :

Java의 ThreadLocal 클래스를 사용하면 동일한 스레드에서만 읽고 쓸 수있는 변수를 만들 수 있습니다. 따라서 두 스레드가 동일한 코드를 실행하고 코드에 ThreadLocal 변수에 대한 참조가 있더라도 두 스레드는 서로의 threadLocal 변수를 볼 수 없습니다.

Thread Java에는 포함되어 있습니다 ThreadLocalMap 그것에.
어디에

Key = One ThreadLocal object shared across threads.
value = Mutable object which has to be used synchronously, this will be instantiated for each thread.

ThreadLocal 달성 :

이제 아래와 같은 (또는없이)와 같이 변한 객체를 보유 할 ThreadLocal 용 래퍼 클래스를 만듭니다. initialValue()).
이제이 래퍼의 getter and setter는 mutable 객체 대신 ThreadLocal 인스턴스에서 작동합니다.

ResdleLocal의 getter ()가 Thread; 그런 다음 InitialValue ()를 호출하여 스레드와 관련하여 개인 사본을 얻습니다.

class SimpleDateFormatInstancePerThread {

    private static final ThreadLocal<SimpleDateFormat> dateFormatHolder = new ThreadLocal<SimpleDateFormat>() {

        @Override
        protected SimpleDateFormat initialValue() {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd") {
                UUID id = UUID.randomUUID();
                @Override
                public String toString() {
                    return id.toString();
                };
            };
            System.out.println("Creating SimpleDateFormat instance " + dateFormat +" for Thread : " + Thread.currentThread().getName());
            return dateFormat;
        }
    };

    /*
     * Every time there is a call for DateFormat, ThreadLocal will return calling
     * Thread's copy of SimpleDateFormat
     */
    public static DateFormat getDateFormatter() {
        return dateFormatHolder.get();
    }

    public static void cleanup() {
        dateFormatHolder.remove();
    }
}

지금 wrapper.getDateFormatter() 전화 할 것입니다 threadlocal.get() 그리고 그것은 그것을 확인할 것입니다 currentThread.threadLocalMap 포함 이것 (ThreadLocal) 인스턴스.
yes 인 경우 해당 ThreadLocal 인스턴스의 값 (simpledateformat)을 반환합니다.
그렇지 않으면이 threadLocal 인스턴스 인 InitialValue ()로 맵을 추가하십시오.

이 돌연변이 성 클래스에서 달성 된 스레드 안전성과 함께; 각 스레드는 자체 변이 가능한 인스턴스로 작동하지만 동일한 ThreadLocal 인스턴스로 작동합니다. 모든 스레드가 키와 동일한 threadLocal 인스턴스를 공유하지만 값과 다른 SimpledateFormat 인스턴스를 공유한다는 것을 의미합니다.

https://github.com/skanagavelu/yt.tech/blob/master/src/threadlocaltest.java

스레드-로컬 변수는 종종 변이 가능한 싱글 톤 또는 글로벌 변수를 기반으로 설계에서 공유하는 것을 방지하는 데 사용됩니다.

연결 풀을 사용하지 않을 때 각 스레드에 대해 별도의 JDBC 연결을 만드는 것과 같은 시나리오에서 사용할 수 있습니다.

private static ThreadLocal<Connection> connectionHolder
           = new ThreadLocal<Connection>() {
      public Connection initialValue() {
           return DriverManager.getConnection(DB_URL);
          }
     };

public static Connection getConnection() {
      return connectionHolder.get();
} 

GetConnection을 호출하면 해당 스레드와 관련된 연결을 반환합니다. DateFormat, Transaction Context와 같은 다른 속성과 동일하게 스레드간에 공유하고 싶지 않습니다.

당신은 또한 동일하게 로컬 변수를 사용할 수 있었지만, 이러한 자원은 일반적으로 생성에 시간을 소비하기 때문에 비즈니스 로직을 수행 할 때마다 계속해서 만들고 싶지 않습니다. 그러나 Threadlocal 값은 스레드 객체 자체에 저장되며 실이 수집 되 자마자 이러한 값도 사라집니다.

이것 링크 ThreadLocal의 사용을 매우 잘 설명합니다.

그만큼 ThreadLocal Java의 클래스를 사용하면 동일한 스레드에서만 읽고 쓸 수있는 변수를 만들 수 있습니다. 따라서 두 스레드가 동일한 코드를 실행하고 코드에 ThreadLocal 변수에 대한 참조가 있더라도 두 스레드는 서로의 threadLocal 변수를 볼 수 없습니다.

더 읽으십시오

참조] ThreadLocal은 공유 객체의 업데이트 문제를 해결할 수 없습니다. 동일한 스레드의 모든 작업에서 공유하는 staticthreadlocal 객체를 사용하는 것이 좋습니다. [필수] remove () 메소드는 특히 스레드가 재사용되는 스레드 풀을 사용할 때 스레드 로컬 변수에 의해 구현되어야합니다. 그렇지 않으면 후속 비즈니스 로직에 영향을 줄 수 있으며 메모리 누출과 같은 예기치 않은 문제가 발생할 수 있습니다.

캐싱, 때때로 동일한 값을 많은 시간을 계산해야하므로 마지막 입력 세트를 메소드에 저장하고 결과를 속도를 높일 수 있습니다. 스레드 로컬 스토리지를 사용하면 잠금에 대해 생각하지 않아도됩니다.

ThreadLocal은 JVM에 의해 특별히 프로비저닝 된 기능으로 스레드만을위한 격리 된 저장 공간을 제공합니다. 인스턴스의 값과 마찬가지로 Scoped 변수는 클래스의 주어진 인스턴스에만 바인딩됩니다. 각 객체에는 유일한 값이 있으며 서로 값을 볼 수 없습니다. threadlocal 변수의 개념은 객체의 의미에서 스레드에 국한되어 있으며, 그것을 만든 다른 스레드를 제외한 다른 스레드는 그것을 볼 수 없습니다. 여기를 봐

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;


public class ThreadId {
private static final AtomicInteger nextId = new AtomicInteger(1000);

// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> nextId.getAndIncrement());


// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
    return threadId.get();
}

public static void main(String[] args) {

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

}
}

ThreadLocal은 객체 재사용 성을 제로 비용으로 달성 할 수있는 매우 쉬운 방법을 제공합니다.

각 업데이트 알림에서 여러 스레드가 변한 캐시 이미지를 생성하는 상황이있었습니다.

각 스레드에서 ThreadLocal을 사용한 다음 각 스레드는 이전 이미지를 재설정 한 다음 각 업데이트 알림의 캐시에서 다시 업데이트해야합니다.

객체 풀의 일반적인 재사용 가능한 객체에는 스레드 안전 비용이 관련되어 있지만이 접근법에는 아무것도 없습니다.

사용에는 3 가지 시나리오가 있습니다 수업 도우미 Multithread 코드의 SimpledateFormat과 마찬가지로 사용하는 것이 가장 좋습니다. ThreadLocal

시나리오

1- 좋아요 객체를 공유하십시오 의 도움으로 잠금 또는 동기화 앱을 만드는 메커니즘 느린

2- a로 사용합니다 로컬 대상 방법 내부

이 시나리오에서 우리가 가지고 있다면 4 스레드 각각 메소드 1000을 호출합니다 그때 우리는 가지고 있습니다
4000 SimpledateFormat 생성 된 개체 GC가 지우기를 기다리고 있습니다

3- 사용 ThreadLocal

우리가 4 개의 실이 있고 우리가 주었다면 각 스레드 하나는 단순화 된 인스턴스를 단순화합니다
그래서 우리는 가지고 있습니다 4 스레드, 4 개 객체 SimpledateFormat의.

자물쇠 메커니즘과 객체 생성 및 파괴가 필요하지 않습니다. (좋은 시간 복잡성과 공간 복잡성)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top