java - 测试 ThreadLocal 成员变量

标签 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。

第一个 print 语句怎么也打印出 1。

怎么了?

最佳答案

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

关于java - 测试 ThreadLocal 成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8410565/

相关文章:

java - 在 Spring Batch 中重置内存数据库

java - FileNotFoundException Java 小程序

c++ - `thread_local` 全局变量什么时候初始化?

c++ - 正确使用和实现单例

clojure - Clojure 中的线程本地计数器

java - 无法获取 Java 线程本地对象中存储的变量的整数值

java - 如何模拟 jdbcTemplate.query(sqlQuery, new Object[] {id, name}, new Mapper())

java - 使用reuseForks配置maven-surefire插件

java - Nashorn 以线程安全的方式

c# - 基本线程问题