2017-02-08 49 views
0

我有一個定期運行的線程。該線程清除並更新數據庫中的數據散列圖。只有在定期線程處理之後才使用變量

說線程每半夜24小時運行一次。在午夜,緩存被清除,然後用數據庫中的數據更新。在更新過程中,只有在線程完成處理後,我如何才能訪問此緩存?當然,我可以確保緩存不是空的。但是,還有其他方法可以做到這一點嗎?

我知道這個問題有點含糊。我正在尋找資源來指導我做自己的研究和調查。

+0

更新之後,您是否希望緩存可用,直至下一個午夜,或者只是一會兒?如果前者,爲什麼不把它設置到一個公開可用的地方(如一個有吸氣劑的領域)?任何人都可以從那個地方讀到,只要變量不爲空,就是他們應該使用的。當然有線程問題,但這本身就是一個整體。 – yshavit

+0

在我提供的這個例子中,直到下一個午夜。根據你的例子,我不需要將它存儲到一個變量中,然後在某個點上覆蓋變量?基本上我想要做的就是在更新發生之前避免與此變量進行交互 – Albert

+0

如果交互只是「存儲引用,然後使用該本地引用進行任何你需要做的事情」,那麼爲什麼你要關心如果有人使用它?換一種說法:如果某人在晚上11:58正確地拿起以前的版本,而在12:01上午「錯誤地」拿起同一個版本,而新的緩存正在計算中,它又有什麼不同? – yshavit

回答

0

使用標誌canGet = true; 從db更新數據之前,使此標誌爲false 現在清除地圖並加載它 這與您建議的方式類似,只是在更新完成時更新變量,更新完成後設置標誌爲true。

同時獲得來自地圖數據,檢查該標誌,如果是可從地圖中獲得的價值

注意:請這個標誌揮發性

0

cacheThread:每24小時

mainThread:你的線程檢查地圖是否填充

有很多方法。最簡單的方法是使用低級別通信工具在單個對象上使用等待和通知以及使用標誌變量來在這兩個線程之間建立通信。主線程將等待標誌爲false並且一旦標誌被設置,緩存線程將通知主線程。

其他複雜的方式包括使用CyclicBarrier/Phaser。使用CycliBarrier,您可以爲兩個線程提供一個屏障對象,並且初始參與方爲2,因此當兩個線程都調用await方法時,主線程將繼續執行,主線程也會重置屏障以便在第二天使用。

mainThread{ 
    //some code 

     barrier.await(); 

    //barrier.reset 
    //required processing on map 

} 
cacheThread{ 
    //Fill map 
     barrier.await(); 

} 
0

說線程每24小時在午夜運行。在午夜,緩存被清除,然後用數據庫中的數據更新。在更新過程中,只有在線程完成處理後,我如何才能訪問此緩存?

這是一個很常見的模式,有很多答案。我傾向於永遠不清除緩存,而是用新的替換緩存。

private volatile Map<?, ?> cacheMap = new HashMap<>(); 
... 
private void updateCache() { 
    Map<?, ?> newCacheMap = new HashMap<>(); 
    // ... fill out the newCacheMap somehow 
    // once it is filled out then you can replace the one in use 
    this.cacheMap = newCacheMap; 
} 

重要的是要注意volatile場,以確保線程看到一個完全公佈緩存它們運行時。

如果內存中的緩存太大而沒有2個副本(舊的和新的),那麼我建議您切換到使用ConcurrentHashMap併爲每個元素添加超時時間。然後,您可以即時更新緩存映射。後臺線程會爲其添加新元素並在運行中刪除舊元素。或者它可以遍歷緩存中的條目,並通過重新將它們放到地圖上來刷新它們。

相關問題