알 기 쉬 운 학습 자바 ThreadLocal
6329 단어 JavaThreadLocal
ThreadLocal 은 변수 로 모든 스 레 드 에 복사 본 을 만 들 었 기 때문에 모든 스 레 드 는 자신의 내부 의 복사 본 변 수 를 방문 할 수 있 고 서로 다른 스 레 드 간 에 서로 간섭 하지 않 습 니 다.본 고 는 실제 장면 을 바탕 으로 ThreadLocal 이 어떻게 사용 하고 내부 실현 체 제 를 소개 할 것 이다.
응용 장면
Parameter 대상 의 데 이 터 는 여러 모듈 에서 사용 해 야 하 며,매개 변수 전달 방식 을 사용 하면 모듈 간 의 결합 성 을 증가 시 킬 수 있 습 니 다.우선 ThreadLocal 로 모듈 간 공유 데 이 터 를 어떻게 실현 하 는 지 살 펴 보 자.
class Parameter {
private static ThreadLocal<Parameter> _parameter= new ThreadLocal<>();
public static Parameter init() {
_parameter.set(new Parameter());
}
public static Parameter get() {
_parameter.get();
}
...
}
모듈 A 에서 Parameter.init 를 통 해 초기 화 합 니 다 스 레 드 Thread 의 측면 에서 볼 때 모든 스 레 드 내부 에 ThreadLocalMap 인 스 턴 스 에 대한 인용 이 있 습 니 다.ThreadLocalMap 인 스 턴 스 는 스 레 드 의 부분 변수 공간 에 해당 하고 스 레 드 각자 의 데 이 터 를 저장 합 니 다.구체 적 으로 다음 과 같 습 니 다.
Entry
Entry 는 Weak Reference 류 에서 계승 되 며 스 레 드 의 개인 변 수 를 저장 하 는 데이터 구조 입 니 다.ThreadLocal 인 스 턴 스 를 인용 하면 ThreadLocal 인 스 턴 스 가 null 이면 table 에서 해당 하 는 Entry 를 삭제 할 수 있 음 을 의미 합 니 다.
class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocalMap내부 에 table 배열 을 사용 하여 Entry 를 저장 합 니 다.기본 크기 INITIALCAPACITY(16),먼저 몇 가지 인 자 를 소개 합 니 다.
size:table 에서 요소 의 수량
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
위의 코드 에서 알 수 있 듯 이:현재 스 레 드 Thread 에서 ThreadLocalMap 인 스 턴 스 를 가 져 옵 니 다
private void set(ThreadLocal<?> key, Object value) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
1.ThreadLocal 의 nextHashCode 방법 으로 hash 값 을 생 성 합 니 다.
private static AtomicInteger nextHashCode = new AtomicInteger();
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}
nextHashCode 방법 을 통 해 알 수 있 듯 이 ThreadLocal 은 한 번 씩 예화 할 때마다 해시 값 은 원자 에 HASH 를 증가 합 니 다.INCREMENT。2.hash&(len-1)를 통 해 table 의 위치 i 를 찾 고 table 의 i 위치 요 소 를 f 로 가정 합 니 다.
3.만약 f!=null,f 의 인용 을 k 로 가정 합 니 다.
5.cleanSomeSlots 를 통 해 오래된 요 소 를 삭제 합 니 다.table 에서 요소 가 삭제 되 지 않 으 면 현재 상황 에서 확장 할 지 여 부 를 판단 해 야 합 니 다.
테이블 확장
만약 에 table 의 요소 수량 이 한도 값 threshold 의 3/4 에 이 르 면 확장 작업 을 할 것 입 니 다.과정 은 매우 간단 합 니 다.
private void resize() {
Entry[] oldTab = table;
int oldLen = oldTab.length;
int newLen = oldLen * 2;
Entry[] newTab = new Entry[newLen];
int count = 0;
for (int j = 0; j < oldLen; ++j) {
Entry e = oldTab[j];
if (e != null) {
ThreadLocal<?> k = e.get();
if (k == null) {
e.value = null; // Help the GC
} else {
int h = k.threadLocalHashCode & (newLen - 1);
while (newTab[h] != null)
h = nextIndex(h, newLen);
newTab[h] = e;
count++;
}
}
}
setThreshold(newLen);
size = count;
table = newTab;
}
새 배열 new Tab 을 새로 만 듭 니 다.크기 는 원래 의 2 배 입 니 다
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();
}
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
현재 스 레 드 의 threadLocals 를 가 져 옵 니 다.
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
Entry[] tab = table;
int len = tab.length;
while (e != null) {
ThreadLocal<?> k = e.get();
if (k == key)
return e;
if (k == null)
expungeStaleEntry(i);
else
i = nextIndex(i, len);
e = tab[i];
}
return null;
}
총결산본 논문 의 소 개 를 통 해 여러분 들 은 ThreadLocal 에 대해 더욱 직관 적 이 고 뚜렷 한 인식 을 가 질 수 있 기 를 바 랍 니 다.
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.