与ThreadLocal和InheritableThreadLocal同步?

时间:2012-11-06 10:43:52

标签: java multithreading concurrency vaadin

我正在实施此thread local pattern之后的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以提供值的继承   父线程到子线程:当创建子线程时,   child接收所有可继承的thread-local的初始值   父对象具有值的变量。通常是孩子的价值观   将与父母的相同;但是,孩子的价值可以   通过覆盖父母的任意功能   这个类中的childValue方法。

     

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

我的工作线程无法获取锁定,因为它没有收到初始值? 我误解了什么吗? 除this problem之外,使用InheritableThreadLocal的潜在缺陷是什么?我应该注意什么?

感谢。

1 个答案:

答案 0 :(得分: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相同,并且它具有相同的同步陷阱。