【发布时间】:2022-01-23 01:54:55
【问题描述】:
正如标题所述,我正在尝试解决一些从 Singleton 读取数据的线程获得空值的问题。我对我们的日志的调查读起来好像是一个并发问题。
Singleton 定义如下:
@Singleton
public class StaticDatabaseEntries {
private static final Map<String,Thing> databaseEntries = new HashMap<>();
@Lock(LockType.READ)
public Thing getThing(String index) {
return databaseEntries.get(index);
}
}
起初我的印象是数据中只有一个元素被破坏,因为对同一项目的访问重复返回 null。对调试条目的进一步访问表明该问题似乎与特定线程隔离。就好像一旦发生任何导致线程上返回 null 的事情都会继续这样做,但仅在受影响的线程上。
此类的早期版本未应用 LockType.READ,因此根据规范假定为 LockType.WRITE。我使用正确的锁部署了更新以启用并发读取。这并没有改善这种情况。
数据在部署时从数据库加载到 HashMap 中,并且在持续时间内保持不变。由于该类未使用@Startup 标记,因此应用程序使用上下文侦听器来触发从数据库加载条目。
由于线程主要执行读取活动,我不认为切换到ConcurrentHashMap 是有益的。我正在考虑删除static final 部分,因为当容器管理并发访问和单例生命周期时,这似乎是不必要的。当容器无法对 EJB 中标记为 final 的事物进行子类化/代理时,我遇到了副作用。
我考虑的另一种可能性是容器软件中存在某种形式的错误。这是在较旧的 Java 1.7 和 JBOSS 6 EAP 上运行的。在最坏的情况下,我将不得不放弃单例模式,而是按需从数据库中加载条目。
【问题讨论】:
-
您是否最终排除了地图中的条目包含空值的简单可能性,因为它是用空值写入的?
-
是的。记录来自数据库的初始负载,表明以后显示为 null 的负载确实存在。在一个线程上的条目变为空之前,服务运行正常,因为日志表明特定元素已被访问/使用。
标签: java multithreading concurrency singleton ejb