자바 다 중 스 레 드(6),ThreadLocal 클래스
개술
ThreadLocal 이 뭐 죠?사실 ThreadLocal 은 스 레 드 의 로 컬 구현 버 전이 아니 라 Thread 가 아니 라 threadlocalbayer(스 레 드 부분 변수)입 니 다.아마도 그것 을 ThreadLocalVar 라 고 명명 하 는 것 이 더 적합 할 것 이다.스 레 드 부분 변수(ThreadLocal)의 실제 기능 은 매우 간단 합 니 다.이 변 수 를 사용 하 는 모든 스 레 드 에 변수 값 의 사본 을 제공 하 는 것 입 니 다.자바 에서 비교적 특수 한 스 레 드 바 인 딩 체제 로 모든 스 레 드 가 자신의 사본 을 독립 적 으로 바 꿀 수 있 으 며 다른 스 레 드 의 사본 과 충돌 하지 않 습 니 다.
스 레 드 의 측면 에서 볼 때 모든 스 레 드 는 스 레 드 부분 변수 사본 에 대한 암시 적 인 인용 을 유지 합 니 다.스 레 드 가 활동 적 이 고 ThreadLocal 인 스 턴 스 가 접근 할 수 있 습 니 다.스 레 드 가 사라 진 후에 스 레 드 부분 인 스 턴 스 의 모든 복사 본 은 쓰레기 로 회수 된다(이 복사 본 에 대한 다른 참조 가 존재 하지 않 는 한).
ThreadLocal 을 통 해 액세스 하 는 데 이 터 는 항상 현재 스 레 드 와 관련 이 있 습 니 다.즉,JVM 은 모든 실행 스 레 드 에 개인 적 인 로 컬 인 스 턴 스 액세스 공간 을 연결 하여 다 중 스 레 드 환경 에서 자주 발생 하 는 동시 방문 문제 에 격 리 체 제 를 제공 합 니 다.
ThreadLocal 은 어떻게 모든 스 레 드 유지 변 수 를 위 한 복사 본 을 만 듭 니까?사실 실현 하 는 사고방식 은 매우 간단 하 다.ThreadLocal 클래스 에 맵 이 하나 있 는데 모든 라인 의 변 수 를 저장 하 는 복사 본 에 사용 된다.
요약 하면 다 중 스 레 드 자원 공유 문제 에 대해 동기 화 체 제 는'시간 으로 공간 을 바꾼다'는 방식 을 사 용 했 고 ThreadLocal 은'공간 으로 시간 을 바꾼다'는 방식 을 사용 했다.전 자 는 하나의 변 수 를 제공 하여 서로 다른 스 레 드 를 줄 지어 방문 하 게 하고 후 자 는 모든 스 레 드 에 변 수 를 제공 하기 때문에 서로 영향 을 주지 않 고 동시에 방문 할 수 있다.
2.API 설명
ThreadLocal()
스 레 드 로 컬 변 수 를 만 듭 니 다.
T get()
이 스 레 드 부분 변수의 현재 스 레 드 던 전의 값 을 되 돌려 줍 니 다.스 레 드 가 처음으로 이 방법 을 호출 하면 이 던 전 을 만 들 고 초기 화 합 니 다.
protected T initialValue()
이 스 레 드 부분 변수의 현재 스 레 드 의 초기 값 을 되 돌려 줍 니 다.스 레 드 에 접근 할 때마다 모든 스 레 드 부분 변 수 를 얻 을 때 이 방법 을 한 번 호출 합 니 다.즉,스 레 드 가 처음으로 get()방법 으로 변 수 를 방문 할 때 입 니 다.스 레 드 가 get 방법 보다 set(T)방법 을 먼저 호출 하면 스 레 드 에서 initialValue 방법 을 다시 호출 하지 않 습 니 다.
이 를 실현 하려 면 null 만 되 돌려 줍 니 다.프로그래머 가 스 레 드 부분 변 수 를 null 이외 의 값 으로 초기 화 하려 면 ThreadLocal 에 하위 클래스 를 만 들 고 이 방법 을 다시 써 야 합 니 다.보통 익명 내부 클래스 를 사용한다.initial Value 의 전형 적 인 실현 은 적당 한 구조 방법 을 호출 하고 새로운 구조의 대상 으로 돌아 갈 것 이다.
void remove()
이 스 레 드 부분 변수의 값 을 제거 합 니 다.이것 은 스 레 드 부분 변수의 저장 수 요 를 줄 이 는 데 도움 이 될 수 있다.이 스 레 드 부분 변 수 를 다시 방문 하면 기본 값 으로 initial Value 를 가 집 니 다.
void set(T value)
이 스 레 드 부분 변수의 현재 스 레 드 던 전의 값 을 지정 값 으로 설정 합 니 다.많은 프로그램 들 이 이 기능 을 필요 로 하지 않 습 니 다.이 기능 들 은 initialValue()방법 에 만 의존 하여 스 레 드 부분 변수의 값 을 설정 합 니 다.
프로그램 에 서 는 일반적으로 initialValue 방법 을 다시 써 서 특정한 초기 값 을 지정 합 니 다.
3.전형 적 인 사례
1.Hiberante 의 Session 도구 류 Hibernateutil
이 클래스 는 Hibernate 공식 문서 의 Hibernateutil 클래스 로 session 관리 에 사 용 됩 니 다.
public class HibernateUtil {
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static final SessionFactory sessionFactory; // SessionFactory
static {
try {
// hibernate.cfg.xml SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
log.error(" SessionFactory !", ex);
throw new ExceptionInInitializerError(ex);
}
}
// session, Hibernate Session
public static final ThreadLocal session = new ThreadLocal();
/**
* Session
* @return Session
* @throws HibernateException
*/
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// Session , Session
if (s == null) {
s = sessionFactory.openSession();
session.set(s); // Session
}
return s;
}
public static void closeSession() throws HibernateException {
// , Session
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
이 클래스 에서 ThreadLocal 의 initialValue()방법 을 다시 쓰 지 않 았 기 때문에 스 레 드 부분 변수 session 의 초기 값 은 null 이 고,currentSession()을 처음 호출 할 때 스 레 드 부분 변수의 get()방법 도 null 입 니 다.따라서 session 에 대해 판단 을 했 습 니 다.null 이면 세 션 을 새로 열 고 스 레 드 부분 변수 session 에 저장 하 는 것 이 매우 관건 입 니 다.이것 은'Public static final ThreadLocal session=new ThreadLocal()'이 만 든 대상 session 이 Hibernate Session 대상 으로 강제 전환 할 수 있 는 이유 입 니 다.
2.다른 인 스 턴 스
빈 을 만 들 고 서로 다른 스 레 드 대상 을 통 해 빈 속성 을 설정 하여 각 스 레 드 빈 대상 의 독립 성 을 확보 합 니 다.
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-23
* Time: 10:45:02
*
*/
public class Student {
private int age = 0; //
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2007-11-23
* Time: 10:53:33
*
*/
public class ThreadLocalDemo implements Runnable {
// studentLocal, Student
private final static ThreadLocal studentLocal = new ThreadLocal();
public static void main(String[] agrs) {
ThreadLocalDemo td = new ThreadLocalDemo();
Thread t1 = new Thread(td, "a");
Thread t2 = new Thread(td, "b");
t1.start();
t2.start();
}
public void run() {
accessStudent();
}
/**
* ,
*/
public void accessStudent() {
//
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running!");
//
Random random = new Random();
int age = random.nextInt(100);
System.out.println("thread " + currentThreadName + " set age to:" + age);
// Student ,
Student student = getStudent();
student.setAge(age);
System.out.println("thread " + currentThreadName + " first read age is:" + student.getAge());
try {
Thread.sleep(500);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("thread " + currentThreadName + " second read age is:" + student.getAge());
}
protected Student getStudent() {
// Student
Student student = (Student) studentLocal.get();
// ,studentLocal.get() null
if (student == null) {
// Student , studentLocal
student = new Student();
studentLocal.set(student);
}
return student;
}
}
:
a is running!
thread a set age to:76
b is running!
thread b set age to:27
thread a first read age is:76
thread b first read age is:27
thread a second read age is:76
thread b second read age is:27
a,b 두 스 레 드 age 가 서로 다른 시간 에 인쇄 한 값 이 똑 같은 것 을 볼 수 있 습 니 다.이 프로그램 은 ThreadLocal 을 통 해 다 중 스 레 드 병행 을 실현 할 뿐만 아니 라 데이터 의 안전성 도 고려 합 니 다.
총화
ThreadLocal 사용 장 소 는 주로 다 중 스 레 드 에서 데이터 데이터 데이터 가 병발 로 인해 일치 하지 않 는 문 제 를 해결 합 니 다.ThreadLocal 은 모든 스 레 드 의 동시 방문 데이터 에 복사 본 을 제공 하고 복사 본 을 방문 하여 업 무 를 수행 합 니 다.이러한 결 과 는 메모리 가 소모 되 었 고 스 레 드 동기 화가 가 져 온 성능 소 모 를 크게 줄 였 으 며 스 레 드 병행 제어 의 복잡 도 를 줄 였 습 니 다.
ThreadLocal 은 원자 형식 을 사용 할 수 없고 Object 형식 만 사용 할 수 있 습 니 다.ThreadLocal 의 사용 은 synchronized 보다 훨씬 간단 합 니 다.
ThreadLocal 과 Synchonized 는 다 중 스 레 드 병행 접근 을 해결 하 는 데 사 용 됩 니 다.그러나 ThreadLocal 과 synchronized 는 본질 적 인 차이 가 있다.synchronized 는 잠 금 체 제 를 이용 하여 변수 나 코드 블록 을 한 스 레 드 에 만 접근 할 수 있 도록 합 니 다.한편,ThreadLocal 은 모든 스 레 드 에 변수의 복사 본 을 제공 하여 모든 스 레 드 가 특정한 시간 에 같은 대상 이 아니 라 여러 스 레 드 가 데이터 에 대한 데이터 공 유 를 격 리 시 켰 다.반면 Synchronized 는 반대로 여러 스 레 드 간 통신 시 데이터 공 유 를 얻 을 수 있 습 니 다.
Synchronized 는 스 레 드 간 데이터 공유 에 사용 되 고 ThreadLocal 은 스 레 드 간 데이터 격 리 에 사 용 됩 니 다.
물론 ThreadLocal 은 synchronized 를 대체 할 수 없습니다.서로 다른 문제 영역 을 처리 합 니 다.Synchronized 는 동기 화 메커니즘 을 실현 하 는 데 사용 되 며 ThreadLocal 보다 더 복잡 합 니 다.
5.ThreadLocal 에서 사용 하 는 일반적인 절차
1.다 중 스 레 드 클래스(예 를 들 어 ThreadDemo 클래스)에서 ThreadLocal 대상 threadXxx 를 만 들 고 스 레 드 간 격 리 처리 대상 xxx 를 저장 합 니 다.
2.ThreadDemo 클래스 에서 격 리 접근 할 데 이 터 를 가 져 오 는 방법 getXxx()를 만 듭 니 다.방법 에서 판단 하면 ThreadLocal 대상 이 null 일 때 new()격 리 접근 형식의 대상 을 만 들 고 응용 할 형식 으로 강제로 전환 해 야 합 니 다.
3.ThreadDemo 류 의 run()방법 에서 getXxx()방법 으로 조작 할 데 이 터 를 얻 으 면 모든 스 레 드 가 하나의 데이터 대상 에 대응 하고 언제든지 이 대상 을 조작 할 수 있 습 니 다.
이상 은 네트워크 에서 원본 코드 를 본 후에 자신의 이 해 를 보 았 습 니 다.ThreadLocal 은'스 레 드 의 로 컬 변수'라 고 부 르 는 것 이 가장 적합 합 니 다.이 복사 본 은 실제 적 으로 현재 스 레 드 인 스 턴 스 의 threadLocals 변수 에 저 장 됩 니 다.즉,t.threadLocals 입 니 다.이 threadLocals 변 수 는 실제 적 으로 ThreadLocal 의 내부 클래스 인 ThreadLocal.ThreadLocalMap 의 인 스 턴 스 입 니 다.ThreadLocalMap 은 실제 맵 입 니 다.현재 ThreadLcoal 인 스 턴 스 를 key 로 저장 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.