在修改java中的entryset值时同步对静态hashmap的访问

时间:2013-12-13 11:37:35

标签: java synchronization hashmap

我有一个hashmap,其中包含Link对象作为值,Integer作为key.which每隔一秒后更新一次,同时从某个不同的线程中的其他类访问它。我想在更新Value部分(api响应后的Link对象)时使hashmap不可访问,并在更新完成后使其可访问。什么是最好的方法来做到这一点。

   class Link{
      int id;
      int currentBWidth;
      //getter and setter
   }

public class Cache implements Runnable {
public static HashMap<Integer, Link> linkDetailsMap;//accessed by some other class
static {
    initMap();
}

private static void initMap() {
    linkDetailsMap = new HashMap<Integer, Link>(667);//needed a hashmap
                                                    with fixed size 500


    for (int count = 0; count < 500; count++) {
        Link link = new Link();
        link.setLinkId(count);
        link.setCurrentBWidth(count);
                    linkDetailsMap.put(link.getLinkId(), link);
    }
}

@Override
public void run() {
    while (true) {
        try {
            // making a rest appi call and modifying link CurrentBWidth in
            // linkDetailsMap
            **for(Map.Entry<Integer, Link> entry:linkDetailsMap.entrySet())
                Link link = entry.getValue();
                link.setCurrentBWidth(//some vallue);
            }**
            Thread.sleep(1000);

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
  ......... ///extra code
}

3 个答案:

答案 0 :(得分:2)

使用ReentrantReadWriteLock保护使用写锁定进行修改并使用读锁定进行读取。你可以同时拥有许多读者,但只有一位作家。这样,当作者持有锁时,读者将被阻止。

答案 1 :(得分:1)

只需在哈希映射上进行同步即可。

在两个线程中都

synchronized (linkDetailsMap) {
    // Do stuff here
}

虽然其中一个线程在同步块内部,但另一个线程无法进入并等待 - 所以在那里完成的任何事情都不会有任何线程问题。

一个很好的替代方案是使用ConcurrentHashMap来存储你的值,我没有立即建议它虽然这里的这一行“我想在更新Value部分(api响应后的链接对象)时无法访问hashmap”建议除了put()操作之外,还有更多的处理要做,并且所有处理都需要保护。

答案 2 :(得分:1)

您可以尝试使用信号量,如下所示。

Semaphore semaphore = new Semaphore(1); //Have this as singleton instance all with the map.
.....
//before write
semaphore.acquire();
//actual write.
semaphore.release()
.....
//Before read check if semaphore is already acquired as below.
if(semaphore.availablePermits() == 1) {
 //Perform read 
}  else {
 //Wait and read later.
}