java - 在这种情况下我需要使用线程安全映射吗?

标签 java mysql multithreading concurrency concurrentmodification

我想用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 对它创建的这个新映射的引用操作正常 - 任何其他并发线程看到信息的旧值或新值 - 两者之间没有任何内容。

不过有几点:

  1. 在这种情况下,您应该使信息成为一个可变字段:public static volatile Map... 以避免值将缓存在处理器缓存中并且在您更改引用时不会更新的情况。
  2. 您编写的任何从信息映射中读取值的代码都需要获取对映射的引用,而且只需要一次,然后使用该引用进行操作。例如:

没关系

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/

相关文章:

java - 程序集始终执行具有依赖项的 jar

java - 通过 Random 类和排序为数组生成数据

php - 生成表中的列总和

mysql - SQL cast() INT 到 CHAR 在 UPDATE 查询中不起作用

java - Spring Async,如何在异步任务执行器中启用请求范围

c# - 使用任务时如何在 STA 线程上运行

java - Spring:同一请求中的JSON数据和文件

Java - 获取数字格式的正则表达式

mysql - MySQL 主从复制的 HAProxy

c++ - 子线程退出时如何通知父线程