需求如下:
Application启动时自动加载一些配置化数据,数据最后作为静态对象存于内存中
数据量很大,所以这个加载应该是异步的后台进程,不能影响界面响应。且正因为数据量很大,正常访问界面时可能已经需要某些配置数据但尚未加载完毕,因此需要提前加载。
解决方案:
首先,对于要加载的数据,建立一个manager管理类,维护其是否已加载完毕的状态。这样,当真正的应用程序进程想要访问或加载数据时可以从中判断是否已被加载过。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Threading; namespace ThreadComponent { public class MasterDataManager { public List<string> MasterDataNameList = new List<string>(); public static Dictionary<string, IList> MasterDataDictionary = new Dictionary<string, IList>(); public static Dictionary<string, bool> MasterDataStatus = new Dictionary<string, bool>(); public void InitMasterData(string[] categoryNames) { for (int j = 0; j < categoryNames.Length; j++) { lock (this) { string categoryName = categoryNames[j]; if (MasterDataStatus.ContainsKey(categoryName) && MasterDataStatus[categoryName]) { continue; } List<string> list = new List<string>(); for (int i = 0; i < 1000000; i++) { list.Add(Thread.CurrentThread.Name + i.ToString()); } if (!MasterDataDictionary.ContainsKey(categoryName)) { MasterDataDictionary.Add(categoryName, list); } else { MasterDataDictionary[categoryName] = list; } if (!MasterDataStatus.ContainsKey(categoryName)) { MasterDataStatus.Add(categoryName, true); } else { MasterDataStatus[categoryName] = true; } Console.WriteLine(Thread.CurrentThread.Name + " " + categoryName); } } } } }
可以看到在InitMasterData方法中使用了lock关键字,暂且按下不表
其次是建立一个两个线程,线程1是background线程,线程2模拟应用程序线程
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadComponent { public class MasterDataThreater { private Thread threadOne; private Thread threadTwo; MasterDataManager manager = new MasterDataManager(); public MasterDataThreater() { threadOne = new Thread(new ThreadStart(ThreadOneRun));//两个线程共同做一件事情 threadTwo = new Thread(new ThreadStart(ThreadTwoRun));//两个线程共同做一件事情 threadOne.Name = "线程1"; threadTwo.Name = "线程2"; } /// <summary> /// 开始工作 /// </summary> public void Action() { threadOne.Start(); threadTwo.Start(); } /// <summary> /// 共同做的工作 /// </summary> private void ThreadOneRun() { string[] categoryName = new string[]{"Country","State","Prefix","Club"}; manager.InitMasterData(categoryName); } /// <summary> /// 共同做的工作 /// </summary> private void ThreadTwoRun() { string[] categoryName = new string[] { "Club", "State", "Prefix", "Country" }; manager.InitMasterData(categoryName); } } }
他们都调用InitMasterData方法,只是初始化数据的顺序不一样。按预想,两个线程应该同时进行,且已经初始化过的数据将不被重复初始化。
以下是结果:
可见两个线程同时合作,并未重复加载数据