我有一个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
}
答案 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.
}