2

我正在按照这个线程本地模式实现一个 vaadin 应用程序。

应用程序的状态由多个工作线程修改。因此,为了通知应用程序其状态已更改,我添加了一个进度指示器。

阅读进度指示器示例,我看到了:

        // All modifications to Vaadin components should be synchronized
        // over application instance. For normal requests this is done
        // by the servlet. Here we are changing the application state
        // via a separate thread.
        synchronized (getApplication()) {
            prosessed();
        }

所以基本上,我想我只需要修改调用来getApplication获取我的应用程序的实例(只需调用getCurrent):

  private static ThreadLocal<MyApplication> currentApplication = new ThreadLocal<MyApplication>();

    @Override
    public void init() {
        setCurrent(this); // So that we immediately have access to the current application

        // initialize mainWindow and other stuff

        // Register a transaction listener that updates our ThreadLocal with each request
        if (getContext() != null) {
            getContext().addTransactionListener(this);
        }   
    }

    /**
     * @return the current application instance
     */
    public static MyApplication getCurrent() {
        return currentApplication.get();
    }

问题是我的工作线程死于饥饿,因为它无法获取应用程序上的互斥锁。vaadin 论坛提供的一种解决方案是使用InheritableThreadLocal。它有效,但我不明白为什么。

从 javadoc :

此类扩展 ThreadLocal 以提供从父线程到子线程的值继承:当创建子线程时,子线程接收父线程具有值的所有可继承线程局部变量的初始值。通常,孩子的价值观与父母的价值观相同;但是,通过覆盖此类中的 childValue 方法,可以使子项的值成为父项的任意函数。

当在变量中维护的每个线程属性(例如,用户 ID、事务 ID)必须自动传输到创建的任何子线程时,可继承的线程局部变量优先于普通线程局部变量使用。

我的工作线程无法获得锁,因为它没有收到初始值?我误解了什么吗?除了这个问题,我应该注意使用 InheritableThreadLocal 的潜在陷阱是什么?

谢谢。

4

1 回答 1

3

理解其工作原理的关键是 ThreadLocal 类中的方法:

static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
   return new ThreadLocalMap(parentMap);
}

它被设计为只能从 Thread 构造函数中调用。方法

protected Object childValue(Object parentValue)

InheritableThreadLocal用于将InheritableThreadLocal子线程中变量的初始值设置ThreadLocal为父线程中变量(作为参数传递)的函数。在创建子线程之前从父线程中调用此方法,默认实现将使子值与父值相同,但我们可以重写该childValue()方法以将子值设置为父值的ThreadLocals函数父线程中的值。默认情况下,childValue()返回相同的输入参数,但再次覆盖该childValue()方法也可能会改变这种行为。

所以InheritableThreadLocal工作起来几乎一样ThreadLocal,并且它具有相同的同步陷阱。

于 2012-11-06T12:00:58.323 回答