测试ThreadLocal成员变量

时间:2011-12-07 04:52:37

标签: java multithreading thread-local

我一直在尝试验证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 个答案:

答案 0 :(得分:1)

对于测试课程,我会从更简单的东西开始。只需在ThreadLocal中存储String或其他内容即可开始,并避免反射调用(setAccessible等)。您的问题最有可能出现在所有这些额外的代码中,而且没有任何内容可归因于ThreadLocal本身。