我正在实施此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的潜在缺陷是什么?我应该注意什么?
感谢。
答案 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
相同,并且它具有相同的同步陷阱。