게임 Java 강의 - ThreadLocal

자바 병발 최고의 실천 을 기억 하고 있 습 니 다.그러나 우 리 는 thread 나 runnable 인 터 페 이 스 를 실현 할 때 이 오 류 를 놓 기 쉬 워 서 이상 한 문 제 를 일 으 켰 다.   다음 의 이 예 를 봅 시다.
 
public class UnsafeTask implements Runnable {  
  
    private Date startDate;  
  
    @Override  
    public void run() {  
        startDate = new Date();  
        System.out.printf("Starting Thread: %s : %s
", Thread.currentThread() .getId(), startDate); try { TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Thread Finished: %s : %s
", Thread.currentThread() .getId(), startDate); } } public class Core { public static void main(String[] args) { UnsafeTask task = new UnsafeTask(); for (int i = 0; i < 10; i++) { Thread thread = new Thread(task); thread.start(); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } }

 
   우 리 는 다음 과 같은 출력 을 보 았 다. 
  
  
Starting Thread: 9 : Thu Feb 27 17:26:34 CST 2014  
Starting Thread: 10 : Thu Feb 27 17:26:36 CST 2014  
Starting Thread: 11 : Thu Feb 27 17:26:38 CST 2014  
Starting Thread: 12 : Thu Feb 27 17:26:40 CST 2014  
Thread Finished: 11 : Thu Feb 27 17:26:40 CST 2014  

   끝 난 스 레 드 가 표 시 된 날 짜 는 방금 시 작 된 스 레 드 의 날짜 와 같 습 니 다. 이 유 는 우리 가 같은 Runnable 인 스 턴 스 에서 여러 스 레 드 를 시 작 했 기 때 문 입 니 다. startDat e 도 메 인 은 여러 스 레 드 간 에 공유 되 었 기 때 문 입 니 다.   어떻게 이 문 제 를 피 합 니까?한 가지 방법 은 하나의 스 레 드 를 Runnable 인 스 턴 스 에 대응 시 키 는 것 이 고, 또 하나의 효과 적 인 방법 은 자바 Concurrency API 가 제공 하 는 ThreadLocal 변 수 를 사용 하 는 것 이다. 이런 방법 은 너무 많은 Runnable 인 스 턴 스 를 만 드 는 것 을 피 할 수 있다.   다음 코드 를 보십시오.
  
import java.util.Date;  
import java.util.concurrent.TimeUnit;  
  
public class SafeTask implements Runnable {  
  
    private static ThreadLocal<Date> startDate = new ThreadLocal<Date>() {  
        protected Date initialValue(){  
            return new Date();  
        }  
    };  
      
    @Override  
    public void run() {  
        System.out.printf("Starting Thread: %s : %s
",Thread. currentThread().getId(),startDate.get()); try { TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("Thread Finished: %s : %s
",Thread. currentThread().getId(),startDate.get()); } }

  
  소스 코드 를 자세히 살 펴 보면 Thread Local 구현 에 Thead LocalMap (주소 해시?) 이 있 습 니 다. 각 Thread 와 값 에 대응 하 는 값 도 메 인 을 저장 합 니 다. map 의 key 는 스 레 드 와 도 메 인의 조합 으로 계산 되 어 모든 스 레 드 가 상 태 를 공유 하지 않 습 니 다.   처음 외 에 도 ThreadLocal 의 get (), set () 방법 을 사용 하여 자신의 상 태 를 업데이트 할 수 있 습 니 다.   JDK 는 A 스 레 드 가 B 스 레 드 를 만 들 면 B 가 A 에서 관련 상태 필드 의 복사 본 을 가 져 올 수 있 도록 더 복잡 한 Inheritable Thread Local 클래스 를 제공 합 니 다.
 

좋은 웹페이지 즐겨찾기