Тестирование переменных-членов ThreadLocal - PullRequest
2 голосов
/ 07 декабря 2011

Я пытался проверить, действительно ли члены 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.

что не так?

1 Ответ

1 голос
/ 07 декабря 2011

Для тестового класса я бы начал с чего-то намного, намного проще. Для начала просто сохраните строку или что-то в ThreadLocal и избегайте вызовов отражений (setAccessible и т. Д.). Ваша проблема, скорее всего, связана со всем этим дополнительным кодом, и не связана с самим ThreadLocal.

...