【问题标题】:Testing ThreadLocal member variables测试 ThreadLocal 成员变量
【发布时间】:2011-12-07 04:52:36
【问题描述】:

我一直在尝试验证 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。

怎么了?

【问题讨论】:

    标签: java multithreading thread-local


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2017-07-06
      • 2019-10-15
      • 2021-02-28
      • 2022-11-02
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      相关资源
      最近更新 更多