我想用java定期从mysql加载一些系统信息,大概10秒一次,用一个线程完成这个,同时有多个线程需要读取这些信息,有两种情况:
1、声明一个public static
map :
public volatile static Map<String, String> info = new HashMap<String, String>();
// Context.java
// start a thread to load from mysql
private void load() {
new Thread(new Runnable() {
while(true) {
// return a map
info = loadFromDB(); // every time a new map
Thread.sleep(5 * 1000); // sleep 5 seconds
}
}).start();
}
// mutiple threads call this function
public String getConfig(String key) {
return Context.map.get(key);
}
正如代码所示,每次线程从数据库加载信息时,都是一个新 map ,我不需要更改 map
内容,这个线程安全吗?
2,可能我想要一个有序的map,读线程需要获取map中的max key,在这种情况下,我应该使用TreeMap
还是ConcurrentSkipListMap
?
更新
将 Map
信息更改为 volatile
以避免 cpu 缓存。
最佳答案
Java 中的单个字段分配是原子的,因此如果您的线程在 loadFromDB()
方法调用中构建了一个新的 hashmap(因此它不会触及现有的信息映射)然后简单地更改值info
对它创建的这个新映射的引用操作正常 - 任何其他并发线程看到信息的旧值或新值 - 两者之间没有任何内容。
不过有几点:
- 在这种情况下,您应该使信息成为一个可变字段:
public static volatile Map...
以避免值将缓存在处理器缓存中并且在您更改引用时不会更新的情况。 - 您编写的任何从信息映射中读取值的代码都需要获取对映射的引用,而且只需要一次,然后使用该引用进行操作。例如:
没关系
Map infoMap = info;
value1 = infoMap.get("key1");
//do something
value2 = infoMap.get("key2");
但这不行
value1 = info.get("value1");
//do soemthing
value2 = info.get("value2");
因为您可能正在从较新的信息 map 中读取 value2。
关于java - 在这种情况下我需要使用线程安全映射吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22279993/