多线程设计

本文关键字:多线程 | 更新日期: 2023-09-27 17:58:39

我有一个程序,它将存储来自某些服务器的一些网络活动数据。为了提高速度,我将设计应用程序,在一个单独的线程中发出每个请求,并将结果放入一个通用字典中,其中键是服务器id,对象是结果类。

然而,服务器的这些响应应该每10分钟保存一次到DB。我不知道我是否知道如何解决这个问题。因此,一些投入会很好。

我想的是锁定结果字典,对结果进行深度克隆,并开始在另一个线程中分析结果,该线程刚刚将结果放入DB中。

我如何最大限度地减少来自request threads的阻塞,以便他们可以尽快开始添加新的结果,但仍然可以从字典中读取?

多线程设计

这个想法是在持久化逻辑触发时将当前状态放在一边,同时将新的输入引导到新的存储中。这是这个任务的基本模式:

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

使用ConcurrentDictionary可以避免锁定字典。使用基于Timer的事件每10分钟运行一个线程,该事件将检查Dictionary的内容并将当前计数项保存到DB中,删除该项,然后开始对保存的内容进行分析。

// 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();