我有一些声明如下的方法:
声明此类使用ThreadLocal
从容器中获取Service
组件。
public class ThreadContext {
private Connector connector;
private static ThreadLocal threadLocal = new ThreadLocal() {
@Override
protected Connector initialValue() {
Service service =
(Service) Container.getComponentInstanceOfType(Service.class);
Connector connector = service.getConnector();
return connector;
}
};
public static Connector get() {
return Connector threadLocal.get();
}
}
Connector
是中产阶级
public class Connector {
public Collection<Result> search() {
User user = ConversationUser.getCurrent()
}
}
宣布ConversationUser
也使用ThreadLocal
public class ConversationUser {
private static ThreadLocal<ConversationUser> current =
new ThreadLocal<ConversationUser>();
public static ConversationUser getCurrent() {
return current.get();//(1)
}
}
然后,我写了一个线程来执行以下操作:
Thread thread = null;
thread = new Thread(new Runnable() {
public void run(){
ThreadContext context = new ThreadContext();
Collection<Result> result = context.get().search();//(2)
resultsTemp.put("File", result);
}
});
thread.start();
此线程正常工作但在第(2)行发生NullPointerException
。
正如我调查的那样,方法在第(1)行返回null。
我真的很困惑。我不明白为什么会出现问题。请给我一些澄清,谢谢。
答案 0 :(得分:4)
您正在初始化ConversationUser.current
至new ThreadLocal<ConversationUser>()
,而不是匿名扩展以覆盖initialValue()
,就像您对ThreadContext.threadLocal
所做的那样。因此,在首次调用get
时,没有什么可以告诉它如何填充自己。由于没有代码调用set
来手动填充,get
会返回null
。
有关更多信息和有用的示例,请参阅ThreadLocal
javadoc。
答案 1 :(得分:0)
我做了一些测试,问题是因为私有静态ThreadLocal
变量,我不知道为什么但这不是将对象链接到ThreadLocal
,似乎对象不存在创建。我需要更多时间来调查它。
无论如何,我看到两种解决方案可以解决这个问题:
将此类创建为Singleton
public class ConversationUser extends ThreadLocal<ConversationUser>{
private static ThreadLocal<ConversationUser> current= null;
@Override
protected ConversationUser initialValue() {
return new ConversationUser();
}
public static ConversationUser getCurrent() {
if (current == null) {
current = new ConversationUser();
}
return current.get();
}
}
// usage ConversationUser.getCurrent()
忘掉这个静态变量并始终通过创建ThreadLocal
对象的新实例来访问它
public class ConversationUser extends ThreadLocal<ConversationUser>{
@Override
protected ConversationUser initialValue() {
return new ConversationUser();
}
}
// usage new ConversationUser().get();