2013-12-13 55 views
0

我有一個hashmap,其中包含Link對象作爲值,Integer作爲key.which在每秒鐘後得到更新,同時從其他類訪問在一些不同的線程中。我想在更新Value部分(api響應之後的鏈接對象)時使hashmap無法訪問,並在更新完成後使其可訪問。什麼是最好的辦法做到這一點。同時訪問靜態hashmap,同時修改java中的entryset值

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 
} 

回答

2

使用ReentrantReadWriteLock來保護使用寫入鎖定和使用讀取鎖定進行讀取的修改。你可以同時有很多讀者,但只有一個作家。這樣,當作者鎖定鎖定時,讀者將被阻止。

+1

一個很好的答案,但在這裏有兩個線程的用例的矯枉過正。 –

+1

@TimB你說得對。但是,我幾乎從來沒有聽說過那個漂亮的n讀者/ 1作家鎖,當你知道它存在時,這非常方便。 – Matthieu

1

只要在散列圖上同步就可以做到這一點。

在兩個線程做

synchronized (linkDetailsMap) { 
    // Do stuff here 
} 

當一個線程是同步塊內的其他不能進入,並會等待 - 所以任何事情在那裏不會有任何線程問題。

一個很好的選擇是使用ConcurrentHashMap來存儲你的價值觀,我沒有立即表明,它雖然爲這條線在這裏「我要讓HashMap中不可訪問,同時更新價值部分(API響應之後,鏈接對象)」表明,有更多的做更多的處理,而不僅僅是put()操作,並且所有的處理都需要保護。

+0

他可以使用ConcurrentHashMap嗎?因爲他沒有更新散列圖 – Sach

+0

@SachinPasalkar是的,但是根據您對使用方式的先驗知識,可以使用'synchronized'手動執行,因爲您可以選擇要鎖定的部分。 – Matthieu

+0

@Matthieu:當你同步地圖時,「你可以選擇你想要鎖定哪個部分」部分工作?根據我的理解,它會鎖定整個地圖 – Sach

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. 
}