@Singleton
@LocalBean
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class DeliverersHolderSingleton {
private volatile Map<String, Deliverer> deliverers;
@PostConstruct
private void init() {
Map<String, Deliverer> deliverersMod = new HashMap<>();
for (String delivererName : delivererNames) {
/*gettig deliverer by name*/
deliverersMod.put(delivererName, deliverer);
}
deliverers = Collections.unmodifiableMap(deliverersMod);
}
public Deliverer getDeliverer(String delivererName) {
return deliverers.get(delivererName);
}
@Schedule(minute="*", hour="*")
public void maintenance() {
init();
}
}
Singleton用于存储数据。数据每分钟更新一次。
是否有可能从unmodifiableMap读取会导致同步问题?是否有可能会在init方法中发生重新排序并发布到集合的链接,但集合未完全填充?
最佳答案
Java内存模型保证there is a happens-before relationship between a write and a subsequent read to a volatile variable。换句话说,如果您写入一个volatile变量并随后读取相同的变量,则可以保证即使涉及多个线程,该写入操作也将是可见的:
在随后每次对该字段进行读取之前,都会写入一个易失字段(第8.3.1.4节)。
它进一步保证了在写操作之前发生的任何操作在读取点上也是可见的(由于程序顺序规则和事前发生关系是可传递的事实)。
您的getDeliverers
方法从volatile变量中读取数据,因此它将看到对deliverers = Collections.unmodifiableMap(deliverersMod);
行进行的最新写操作以及填充映射的先前操作。
因此,您的代码是线程安全的,并且getDeliverers
方法将基于最新版本的地图返回结果。