파쇄의 ThreadLocal 인터뷰! ! !

설명

면접관은 다음의 ThreadLocal의 이해 중 일부에 대해 말해.

그래서 우리는 그것을 어떻게 대답 할 수 있습니까? ? ? ? 또한 생각할 수에서 제로 참조 아래에 숙고;

  • ThreadLocal를 어떤 장소에 사용?

  • 세부 사항 중 일부의 ThreadLocal!

  • 의 ThreadLocal의 모범 사례!

  • 생각

ThreadLocal를 어떤 장소에 사용?

어딘가에 이전에 사용 논의의 ThreadLocal에서 만 스레드에서, 다음의 ThreadLocal에 대해 얘기하지 않는 경우 명확하고,하자 의 ThreadLocal 멀티 스레드 장면입니다! ! !

클래스 2까지의 ThreadLocal 유도를 사용 :

  • 어떤 원하는 장소에서 얻을 수있는 쓰레드 컨텍스트 정보를 저장! ! !

  • 스레드 안전하지 않도록 특정 상황 스레드 안전으로 인한 성능 손실 동기화해야합니다 고려할 필요가! ! !

어떤 원하는 장소에서 얻을 수있는 쓰레드 컨텍스트 정보를 저장! ! !

때문에의 ThreadLocal의 특성으로 동일한 스레드는 당신이 얻을 수있는 후속 장소, 장소에 설정됩니다. 쓰레드 컨텍스트 정보를 저장하는 데 사용할 수 있습니다.

이러한 후속 동료 캐릭터 각각의 요청으로, ThreadLocal를 세트로 수행 될 수있는 방법을 일반적인 기록 임의로 ID를 얻을 취득 요구에 후속하는 방법 함께 연결되도록 상기 전체 요구를 기록 할 필요가있다.

예를 들어, 각각 동일한 DAO 연결을 얻을 수 있도록, 트랜잭션 롤백이 제출 및 기타 작업을 할 수 있습니다, ThreadLocal를 저장 연결 스프링의 트랜잭션 관리,있다.

참고 :  이 유용한 ThreadLocal를 종종 프레임 워크 내부의 우수에 사용되는, 우리는 일반적으로 작은 접촉했지만, 다음과 같은 경우 우리가 좀 더 터치!

스레드 안전하지 않도록 특정 상황 스레드 안전으로 인한 성능 손실 동기화해야합니다 고려할 필요가! ! !

ThreadLocal를 동시 멀티 스레드 프로그램의 문제를 해결하는 새로운 방법을 제공합니다. ThreadLocal를하지만 제한이는의 알리 사양을 살펴 보자 :


1


각 스레드는 읽고, 그래서 ThreadLocal를 스레드의 데이터가 영향을 미치지 않습니다 서로 격리 쓰기 의 ThreadLocal 문제 공유 객체 업데이트를 해결할 수 없다!

정보없이 공유하기 때문에, 거기에 따라서 어떤 경우에는 성능 손실 보안 스레드를 확보, 자연적인 경쟁 문제가없고, 스레드 안전을 제공 동기화해야합니다 고려해야 할 경우의 일부를 피하기! ! !

이러한 장면도 언급 알리 사양 :


1


세부 사항 중 일부의 ThreadLocal!

ThreaLocal使用示例代码:

public class ThreadLocalTest {     
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();     
public static void main(String[] args) {         
new Thread(() -> {             
try {                 
for (int i = 0; i < 100; i++) {                     
threadLocal.set(i);                     
System.out.println(Thread.currentThread().getName() + "====" + threadLocal.get());                     
try {                         
Thread.sleep(200);                     
} catch (InterruptedException e) {                         
e.printStackTrace();                     
}                 
}             
} finally {                 
threadLocal.remove();             
}         
}, 
"threadLocal1").start();         
new Thread(() -> {             
try {                 
for (int i = 0; i < 100; i++) {                     
System.out.println(Thread.currentThread().getName() + "====" + threadLocal.get());                     
try {                         
Thread.sleep(200);                     
} catch (InterruptedException e) {                         
e.printStackTrace();                     
}                 
}             
} finally {                 
threadLocal.remove();             
}         
}, 
"threadLocal2").start();     
} 
}

代码截图:

1


代码运行结果:


1


从运行的结果我们可以看到threadLocal1进行set值对threadLocal2并没有任何影响!

Thread、ThreadLocalMap、ThreadLocal总览图


1



1


Thread类有属性变量threadLocals (类型是ThreadLocal.ThreadLocalMap),也就是说每个线程有一个自己的ThreadLocalMap ,所以每个线程往这个ThreadLocal中读写隔离的,并且是互相不会影响的。

一个ThreadLocal只能存储一个Object对象,如果需要存储多个Object对象那么就需要多个ThreadLocal!!!

如图:


1


看到上面的几个图,大概思路应该都清晰了,我们Entry的key指向ThreadLocal用虚线表示弱引用 ,下面我们来看看ThreadLocalMap:


1


java对象的引用包括 : 强引用,软引用,弱引用,虚引用 。

因为这里涉及到弱引用,简单说明下:

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,该对象仅仅被弱引用关联,那么就会被回收。

当仅仅只有ThreadLocalMap中的Entry的key指向ThreadLocal的时候,ThreadLocal会进行回收的!!!

ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是Entry是强引用,那么Entry里面存储的Object,并没有办法进行回收,所以ThreadLocalMap 做了一些额外的回收工作。


1


虽然做了但是也会存在内存泄漏风险(我没有遇到过,网上很多类似场景,所以会提到后面的ThreadLocal最佳实践!!!

ThreadLocal的最佳实践!

ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是Entry是强引用,那么Entry里面存储的Object,并没有办法进行回收,所以ThreadLocalMap 做了一些额外的回收工作。


1


참고 :  많은 경우에, 우리는 기본 스레드를 파괴하지 않습니다, 멈추지 않는 스레드 풀 장면을 사용하고 있습니다! ! !

수명주기가 세트 얻을 그래서 방법에 대한 추가 특정 조건 청소에 호출하지만 비록 우리가 내부의 ThreadLocal에 매우 큰 대상 개체를 설정하면, 매우 긴 스레드의 때문에 ThreadLocalMap에, 쓰레기 수집 이후의 ThreadLocal 해당의 키 입력이 null이 될 수 있지만 후속 작업 세트에, 다른 방법을 얻을 것이다.

그래서 가장 좋은 방법은, 우리는 정리 remove 메소드를 호출 주도권을 사용할 수 없습니다.


1


여기에 또 다른 장점 정적으로 정의의 ThreadLocal 인해의 ThreadLocal의 강한 참조로, 다음 ThreadLocalMap 항상 존재하고 실행 시간을 제거합니다 해당 항목의 키에 제대로 위치 및 삭제 할 수 있다는 것입니다! ! !

가장 좋은 방법은 다음과 같아야합니다

코드를 복사 {의 ThreadLocal 객체 .remove ()} 마지막으로 {// 다른 비즈니스 로직을} 시도


1


생각

인터뷰를하는 경우, 개인적으로, 위의 내용에 대해 이야기 할 수 있습니다 넣어 아주 좋은 느낄 수있는, 아주 완벽한에 대답했다. 그러나 다음과 같은 대답 할 수 있다면, 더욱 완벽.

ThreadLocal를 들어, 나는 인 Netty 소스를보고 있었다뿐만 아니라 FastThreadLocal에 대해 알고, 일련의 컨텐츠를 xxxxx는, 그것은 업그레이드입니다.


1


나는 FastThreadLocal 처리량이 약 3 배 jdkThreadLocal이며, 로컬로 테스트했습니다.



추천

출처blog.51cto.com/14378044/2416748