2013-02-10 79 views
0

我有一個程序將存儲來自某些服務器的一些網絡活動數據。爲了提高速度,我將設計應用程序在一個單獨的線程中創建每個請求,並將結果放入一個通用字典中,其中鍵是服務器ID,對象是結果類。多線程設計

但是,服務器的這種響應應該每10分鐘保存到數據庫。我不知道我是否有任何好主意如何解決這個問題。所以一些輸入會很好。

我想到的是鎖定結果字典並對結果進行深層克隆,並開始分析另一個線程中的結果,並將其放入數據庫中。

我怎樣才能最大限度地減少從request threads阻塞,以便他們可以開始添加新的結果儘快,但仍然從字典中讀取?

+1

只需將字典換成新字典即可。非常快,不要忘記鎖定。 – 2013-02-10 17:52:48

回答

1

您可以避免通過使用ConcurrentDictionary來處理鎖定字典。使用基於計時器的事件每10分鐘運行一次線程,這些事件將檢查詞典的內容並將當前計數項目保存到您的數據庫,刪除它們,然後開始對保存的內容進行分析。

// myCD is your concurrent dictionary 
// every 10 mins 
var myCDClone = myCD.MemberwiseClone(); 
// save to DB using myCDClone 
// using myCDClone.Keys delete everything saved up from myCD 
// myCDClone.Clear(); 
+0

即使CD中沒有任何線程安全列表作爲對象,是否可以克隆它? ConcurrentDictionary >如果列表在同一時刻被修改會怎麼樣? – 2013-02-10 19:15:08

+0

沒有併發性不會滲透到所有keyvaluepair對象,只是字典訪問。 – allen 2013-02-11 03:35:13

2

這個想法是在持續邏輯觸發時將當前狀態放在一邊,而將新輸入指向新存儲。這是此任務的基本模式:

class PeriodicPersist{ 

    // Map must be volatile, persist may look at a stale copy 
    private volatile Map<String, String> keyToResultMap = new HashMap<String, String>(); 

    public void newResult(String key, String result) { 
     synchronized(keyToResultMap) { // Will not enter if in the beginning of persist 
      keyToResultMap.put(key,result); 
     } 
    } 

    public void persist(){ 
     Map<String, String> tempMap; 
     synchronized (keyToResultMap) { // will not enter if a new result is being added just now. 
      if(keyToResultMap.size() == 0) { 
       return; 
      } 

      tempMap = keyToResultMap; 
      keyToResultMap = new HashMap<String, String>(); 
     } 

     // download freshMap to the DB OUTSIDE the lock 
    } 
}