You can benefit from an AtomicReference in cases where multiple threads access (common) configuration data that can be refreshed at any given moment. Refreshing usually happens by one thread (after a certain event or a certain period), but if multiple threads can refresh at the same time, you need some extra locking (see code example below).
The threads getting the configuration data must re-use the returned instance of the configuration data where necessary to prevent mixing old configuration data with new configuration data. This usually means creating a separate class with the configuration data and methods that use the configuration data. But you'll need that anyway to work with the AtomicReference.
The following code example should give you an idea about how to use an AtomicReference:
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Q20708889 {
private static final Object reloadLock = new Object();
private static final AtomicInteger reloadCount = new AtomicInteger();
private AtomicReference<DbSettings> dbSettingsRef = new AtomicReference<DbSettings>();
public DbSettings getDbSettings() {
DbSettings dbs = dbSettingsRef.get();
if (dbs == null) {
dbs = reload();
}
return dbs;
}
public DbSettings reload() {
DbSettings dbs = null;
int rld = reloadCount.get();
synchronized (reloadLock) {
if (rld < reloadCount.get()) {
// Reload was already done
dbs = dbSettingsRef.get();
} else {
reloadCount.incrementAndGet();
dbs = new DbSettings();
dbs.load();
dbSettingsRef.set(dbs);
}
}
return dbs;
}
class DbSettings {
private HashMap<String, HashMap<String, String>> theSettings;
public void load() {
theSettings = new HashMap<String, HashMap<String,String>>();
// getting resources from the database
}
public String getValueSettings(String groupName, String keyName) {
String value = null;
HashMap<String, String> group = theSettings.get(groupName);
if (group != null && !group.isEmpty()) {
value = group.get(keyName);
}
return value;
}
}
}