2011-12-07 93 views
2

我一直在尝试验证ThreadLocal成员是否确实在不同的线程中有所不同。测试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()); 

     } 



} 

因此第1次印刷的说法应该打印出2,第二个要打印出1

如何有史以来第一张印刷声明也打印出1.

有什么不对?

回答

1

对于一个测试类,我会从很多东西开始,更简单一些。只需在ThreadLocal中存储一个字符串或一些东西,并避免反射调用(setAccessible等)。您的问题很可能出现在所有这些额外的代码中,并且由于ThreadLocal本身而不存在。

+0

谢谢。这有帮助。 – user1084874