2011-12-07 4 views
2

ThreadLocal 멤버가 실제로 다른 스레드에서 다른지 확인하려고했습니다.Testing ThreadLocal 멤버 변수

이것은 여러 스레드간에 공유하고있는 객체의 TestClass입니다. 다음

public class TestClass { 

    private static Set<Integer> setI; 

    private static ThreadLocal<Set<String>> setS; 



    public TestClass() { 

      Set<String> temp = new HashSet<String>(); 

      for (int i=0; i<=4; i++) { 

        setI.add(i); 

        temp.add(Integer.toString(i)); 

      } 

      setS.set(temp); 

    } 


    static { 

      setI = new HashSet<Integer>(); 

      setS = new ThreadLocal<Set<String>>() { 

        protected Set<String> initialValue() { 

          return new HashSet<String>(); 

        } 

      }; 

    } 



    public static void addToIntegerSet(int i) { 

      synchronized(setI) { 

        setI.add(i); 

      } 

    } 



    public static void addToStringSet(String str) { 

      Set<String> sets = setS.get(); 

      sets.add(str); 

      setS.set(sets); 

    } 

} 

내가 이것을 테스트하는 데 사용하는 클래스입니다 : -

package personal; 



import java.util.*; 

import personal.TestClass; 

import java.lang.reflect.Field; 



public class Test2 { 



     private static TestClass testObj; 

     private static Set<Set<String>> testStringSet; 

     private static Set<Set<Integer>> testIntegerSet; 



     static { 

       testObj = new TestClass(); 

       testStringSet = new HashSet<Set<String>>(); 

       testIntegerSet = new HashSet<Set<Integer>>(); 

     } 



     private static void addToStringSet(Set<String> sets) { 

       synchronized(testStringSet) { 

         testStringSet.add(sets); 

       } 

     } 



     private static void addToIntegerSet(Set<Integer> sets) { 

       synchronized(testIntegerSet) { 

         testIntegerSet.add(sets); 

       } 

     } 



     private static int getTestIntegerSetSize() { 

       synchronized(testIntegerSet) { 

         return testIntegerSet.size(); 

       } 

     } 



     private static int getTestStringSetSize() { 

       synchronized(testStringSet) { 

         return testStringSet.size(); 

       } 

     } 



     private static class MyRunnable implements Runnable { 

       private TestClass tc; 

       private String name; 

       public MyRunnable(TestClass tc, int i) { 

         this.name = "Thread:- " + Integer.toString(i); 

         this.tc = tc; 

       } 

       @Override 

       public void run() { 

         try { 

           Field f1 = tc.getClass().getDeclaredField("setS"); 

           Field f2 = tc.getClass().getDeclaredField("setI"); 

           f1.setAccessible(true); 

           f2.setAccessible(true); 

           Set<String> v1 = (Set<String>)(((ThreadLocal<Set<String>>)(f1.get(tc))).get()); 

           Set<Integer> v2 = (Set<Integer>) f2.get(tc); 

           addToIntegerSet(v2); 

           addToStringSet(v1); 

         } catch (Exception exp) { 

           System.out.println(exp); 

         } 

       } 

     } 



     public static void main(String[] args) { 

       for (int i=1; i<=2; i++) { 

         (new Thread (new MyRunnable(testObj,i))).start(); 

       } 

       try { 

         Thread.sleep(5);      

       } catch (Exception exp) { 

         System.out.println(exp); 

       } 

       System.out.println(getTestStringSetSize()); 

       System.out.println(getTestIntegerSetSize()); 

     } 



} 

따라서 첫 번째 인쇄 문 2를 인쇄해야하며, 두 번째는 인쇄해야 알아 1.

방법 첫 번째 인쇄 진술서도 1을 인쇄합니다.

무엇이 잘못 되었습니까?

답변

1

테스트 클래스의 경우 훨씬 간단하게 시작하겠다. ThreadLocal에 문자열 또는 어떤 것을 저장하고 반사 호출 (setAccessible 등)을 피하십시오. 문제는이 모든 추가 코드에서 발생할 가능성이 높으며 ThreadLocal 자체로 인한 문제는 아닙니다.

+0

감사합니다. 그것은 도움이되었습니다. – user1084874