설명
면접관은 다음의 ThreadLocal의 이해 중 일부에 대해 말해.
그래서 우리는 그것을 어떻게 대답 할 수 있습니까? ? ? ? 또한 생각할 수에서 제로 참조 아래에 숙고;
ThreadLocal를 어떤 장소에 사용?
세부 사항 중 일부의 ThreadLocal!
의 ThreadLocal의 모범 사례!
생각
ThreadLocal를 어떤 장소에 사용?
어딘가에 이전에 사용 논의의 ThreadLocal에서 만 스레드에서, 다음의 ThreadLocal에 대해 얘기하지 않는 경우 명확하고,하자 의 ThreadLocal 멀티 스레드 장면입니다! ! !
클래스 2까지의 ThreadLocal 유도를 사용 :
어떤 원하는 장소에서 얻을 수있는 쓰레드 컨텍스트 정보를 저장! ! !
스레드 안전하지 않도록 특정 상황 스레드 안전으로 인한 성능 손실 동기화해야합니다 고려할 필요가! ! !
어떤 원하는 장소에서 얻을 수있는 쓰레드 컨텍스트 정보를 저장! ! !
때문에의 ThreadLocal의 특성으로 동일한 스레드는 당신이 얻을 수있는 후속 장소, 장소에 설정됩니다. 쓰레드 컨텍스트 정보를 저장하는 데 사용할 수 있습니다.
이러한 후속 동료 캐릭터 각각의 요청으로, ThreadLocal를 세트로 수행 될 수있는 방법을 일반적인 기록 임의로 ID를 얻을 취득 요구에 후속하는 방법 함께 연결되도록 상기 전체 요구를 기록 할 필요가있다.
예를 들어, 각각 동일한 DAO 연결을 얻을 수 있도록, 트랜잭션 롤백이 제출 및 기타 작업을 할 수 있습니다, ThreadLocal를 저장 연결 스프링의 트랜잭션 관리,있다.
참고 : 이 유용한 ThreadLocal를 종종 프레임 워크 내부의 우수에 사용되는, 우리는 일반적으로 작은 접촉했지만, 다음과 같은 경우 우리가 좀 더 터치!
스레드 안전하지 않도록 특정 상황 스레드 안전으로 인한 성능 손실 동기화해야합니다 고려할 필요가! ! !
ThreadLocal를 동시 멀티 스레드 프로그램의 문제를 해결하는 새로운 방법을 제공합니다. ThreadLocal를하지만 제한이는의 알리 사양을 살펴 보자 :
각 스레드는 읽고, 그래서 ThreadLocal를 스레드의 데이터가 영향을 미치지 않습니다 서로 격리 쓰기 의 ThreadLocal 문제 공유 객체 업데이트를 해결할 수 없다!
정보없이 공유하기 때문에, 거기에 따라서 어떤 경우에는 성능 손실 보안 스레드를 확보, 자연적인 경쟁 문제가없고, 스레드 안전을 제공 동기화해야합니다 고려해야 할 경우의 일부를 피하기! ! !
이러한 장면도 언급 알리 사양 :
세부 사항 중 일부의 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(); } }
代码截图:
代码运行结果:
从运行的结果我们可以看到threadLocal1进行set值对threadLocal2并没有任何影响!
Thread、ThreadLocalMap、ThreadLocal总览图
Thread类有属性变量threadLocals (类型是ThreadLocal.ThreadLocalMap),也就是说每个线程有一个自己的ThreadLocalMap ,所以每个线程往这个ThreadLocal中读写隔离的,并且是互相不会影响的。
一个ThreadLocal只能存储一个Object对象,如果需要存储多个Object对象那么就需要多个ThreadLocal!!!
如图:
看到上面的几个图,大概思路应该都清晰了,我们Entry的key指向ThreadLocal用虚线表示弱引用 ,下面我们来看看ThreadLocalMap:
java对象的引用包括 : 强引用,软引用,弱引用,虚引用 。
因为这里涉及到弱引用,简单说明下:
弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,该对象仅仅被弱引用关联,那么就会被回收。
当仅仅只有ThreadLocalMap中的Entry的key指向ThreadLocal的时候,ThreadLocal会进行回收的!!!
ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是Entry是强引用,那么Entry里面存储的Object,并没有办法进行回收,所以ThreadLocalMap 做了一些额外的回收工作。
虽然做了但是也会存在内存泄漏风险(我没有遇到过,网上很多类似场景,所以会提到后面的ThreadLocal最佳实践!!!)
ThreadLocal的最佳实践!
ThreadLocal被垃圾回收后,在ThreadLocalMap里对应的Entry的键值会变成null,但是Entry是强引用,那么Entry里面存储的Object,并没有办法进行回收,所以ThreadLocalMap 做了一些额外的回收工作。
참고 : 많은 경우에, 우리는 기본 스레드를 파괴하지 않습니다, 멈추지 않는 스레드 풀 장면을 사용하고 있습니다! ! !
수명주기가 세트 얻을 그래서 방법에 대한 추가 특정 조건 청소에 호출하지만 비록 우리가 내부의 ThreadLocal에 매우 큰 대상 개체를 설정하면, 매우 긴 스레드의 때문에 ThreadLocalMap에, 쓰레기 수집 이후의 ThreadLocal 해당의 키 입력이 null이 될 수 있지만 후속 작업 세트에, 다른 방법을 얻을 것이다.
그래서 가장 좋은 방법은, 우리는 정리 remove 메소드를 호출 주도권을 사용할 수 없습니다.
여기에 또 다른 장점 정적으로 정의의 ThreadLocal 인해의 ThreadLocal의 강한 참조로, 다음 ThreadLocalMap 항상 존재하고 실행 시간을 제거합니다 해당 항목의 키에 제대로 위치 및 삭제 할 수 있다는 것입니다! ! !
가장 좋은 방법은 다음과 같아야합니다
코드를 복사 {의 ThreadLocal 객체 .remove ()} 마지막으로 {// 다른 비즈니스 로직을} 시도
생각
인터뷰를하는 경우, 개인적으로, 위의 내용에 대해 이야기 할 수 있습니다 넣어 아주 좋은 느낄 수있는, 아주 완벽한에 대답했다. 그러나 다음과 같은 대답 할 수 있다면, 더욱 완벽.
ThreadLocal를 들어, 나는 인 Netty 소스를보고 있었다뿐만 아니라 FastThreadLocal에 대해 알고, 일련의 컨텐츠를 xxxxx는, 그것은 업그레이드입니다.
나는 FastThreadLocal 처리량이 약 3 배 jdkThreadLocal이며, 로컬로 테스트했습니다.