我正在实现一个遵循这个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以提供从父线程到子线程的值继承:当创建子线程时,子线程接收父线程具有值的所有可继承线程局部变量的初始值。通常,子节点的值与父节点的值相同;但是,通过重写该类中的childValue方法,可以使子对象的值成为父对象的任意函数。
当在变量中维护的每线程属性(例如,用户ID、事务ID)必须被自动传输到所创建的任何子线程时,优先于普通线程局部变量使用可继承线程局部变量。
我的辅助线程无法获得锁,因为它没有接收初始值?我是不是误解了什么?除了this problem,我应该注意使用InheritableThreadLocal的潜在陷阱是什么?
谢谢
1条答案
按热度按时间5gfr0r5j1#
理解它如何工作的关键是
ThreadLocal
类中的方法:它被设计为只能从Thread构造函数调用。该方法
用于将子线程中的
InheritableThreadLocal
变量的初始值设置为父线程中的ThreadLocal
变量(作为参数传递)的函数。这个方法在创建子线程之前从父线程中调用,默认实现将使子线程的值与父线程的值相同,但是我们可以重写childValue()
方法,将子线程的值设置为父线程中具有值的ThreadLocals
的父线程值的函数。默认情况下,childValue()
返回相同的输入参数,但是childValue()
方法的重写也可能会更改此行为。因此,
InheritableThreadLocal
的工作方式几乎与ThreadLocal
相似,并且具有相同的同步缺陷。