0

在下面的代码中,静态方法getCustomerIdByClientKey将被高吞吐量环境中的多个线程使用。

静态方法loadCustomers将每 10 分钟左右调用一次,以使缓存无效并加载新的客户集。可以添加或删除客户。

我担心的线是clientKeyToCustomerId = newClientKeyToCustomerId;

如果一个线程在clientKeyToCustomerId重新分配时当前正在使用映射,该线程会抛出异常,还是会继续在它的内存空间中没有问题,或者它会杀死整个 JVM?:)

我不想同步访问地图的块,因为我认为这会对性能产生负面影响。

我不想map.clear()简单地调用,因为访问查找的线程将在不应该返回空结果时返回空结果。

如果更换地图会导致问题,你会采取什么方法来解决这个问题?

package com.mycompany.key;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mycompany.dao.CustomerDao;
import com.mycompany.model.Customer;

public class CustomerManager {

    private static Map<String, String> clientKeyToCustomerId = 
                   new HashMap<String, String>();

    public static void loadCustomers() {
        List<Customer> allCustomers = new CustomerDao().loadAll();
        Map<String, String> newClientKeyToCustomerId = new HashMap<String, String>();
        for (Customer customer : allCustomers) {
            newClientKeyToCustomerId.put(customer.getActiveKey1(),
                    customer.getCustomerId());
            newClientKeyToCustomerId.put(customer.getActiveKey2(),
                    customer.getCustomerId());
        }
        clientKeyToCustomerId = newClientKeyToCustomerId;
    }

    public static String getCustomerIdByClientKey(String pClientKey) {
        return clientKeyToCustomerId.get(pClientKey);
    }

}
4

1 回答 1

1

在被告知阅读 volatile 之后,我认为这个问题中接受的答案解决了Volatile HashMap vs ConcurrentHashMap。我修改了下面的代码。volatile 关键字停止任何线程本地缓存映射的线程。

当前从旧地图读取的任何线程都将过时,但从业务角度来看这是可以的。

package com.mycompany.key;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mycompany.dao.CustomerDao;
import com.mycompany.model.Customer;

public class CustomerManager {

    //private static Map<String, String> clientKeyToCustomerId = 
    // new HashMap<String, String>();
    private volatile static Map<String, String> clientKeyToCustomerId = 
               new HashMap<String, String>();

    public static void loadCustomers() {
        List<Customer> allCustomers = new CustomerDao().loadAll();
        Map<String, String> newClientKeyToCustomerId = new HashMap<String, String>();
        for (Customer customer : allCustomers) {
            newClientKeyToCustomerId.put(customer.getActiveKey1(),
                    customer.getCustomerId());
            newClientKeyToCustomerId.put(customer.getActiveKey2(),
                    customer.getCustomerId());
        }
        clientKeyToCustomerId = newClientKeyToCustomerId;
    }

    public static String getCustomerIdByClientKey(String pClientKey) {
        return clientKeyToCustomerId.get(pClientKey);
    }

}
于 2013-02-28T14:55:52.290 回答