多线程设计
本文关键字:多线程 | 更新日期: 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();