InheritableThreadlocal值在java中自动更改

时间:2018-02-16 07:42:01

标签: java threadpool thread-local

我正在使用InheritableThreadlocal HashMap来存储我的所有threadlocals。

class MyThreadLocalMap {
    private final static ThreadLocal<HashMap<String, Object>> THREAD_VARIABLES = new InheritableThreadLocal<HashMap<String, Object>>() {
        @Override
        protected HashMap<String, Object> initialValue() {
            return new HashMap<>();
        }
    };

    public static Object get(String name) {
        return THREAD_VARIABLES.get().get(name);
    }

    public static Object set(String name, Object value) {
        Object currentValue = get(name);
        THREAD_VARIABLES.get().put(name, value);
        return currentValue;
    }
}

这很好用,直到最后一天出现一个奇怪的错误。

我正在使用tomcat服务器来运行我的Web应用程序。我使用ScheduledThreadPoolExecutor创建了一个线程池并在多个线程中运行任务。我的代码的缩写看起来与此类似。

MyThreadLocalMap.set("MyKey", 1);
....
....
Object obj = MyThreadLocalMap.get("MyKey");
if(!Integer.valueOf(1).equals(obj))
    throw new Exception("threadlocal mismatch!");
....
....
MyThreadLocalMap.set("MyKey", null);

上面的代码将在多个线程中执行,因为我使用的是线程池,所以相同的线程将被重用。

奇怪的是,在大约5个线程成功完成执行后,其中一个线程抛出了“threadlocal mismatch”异常!

我的主要怀疑是使用InheritableThreadLocal(这对于内存泄漏是臭名昭着的)

我尝试重试以重现开发服务器中的问题,但我无法解决。我不想冒险在生产服务器上测试它。

1 个答案:

答案 0 :(得分:1)

您的地图在父线程中实例化。 InheritedThreadLocal值是&#34;取下&#34;对孩子们来说。

虽然多个子线程可能并行执行。显示的部分,一个线程可以设置&#34; MyKey&#34;当另一个子线程正在读取它时为null。

所以这是一个真正的问题。您应该在设置和读取之间同步代码。或者使用普通的ThreadLocal。

顺便说一下。你应该同步访问地图。