在工做的任务中,须要对客户端和服务端 通讯包进行落地。把这个作成通用的模块,在高并发和多线程下,也可以工做。算法
在查阅了大众化日志方案后,决定采用:写日志和写文件分离的方式进行。大概内容图:安全
须要记录是通讯包,将须要记录的通讯包推送到队列,再由一个专门的线程去读取队列,将出队列的数据写到文件中。这样将每次直接IO瓶颈,转化成存储队列的大小,瓶颈变成了内存的大小。上代码:bash
// 扫描队列,写文件的线程
private static readonly Thread LogThread;
// 自定义线程安全的Queue
private static readonly ConcurrentQueue<Message> LogQueue;
// 多线程下,操做统一资源的锁
private static readonly object SyncRoot;
// 在队列没有数据时,线程中止扫描标志
private static readonly AutoResetEvent AutoReset = null;
复制代码
// 构造函数
static Utils()
{
AutoReset = new AutoResetEvent(false);
SyncRoot = new object();
LogThread = new Thread(WriteLog);
LogQueue = new ConcurrentQueue<Message>();
LogThread.Start();
}
复制代码
// 记录日志
public static void Log(List<Message> msg)
{
foreach (var item in msg)
{
// 队列入队
LogQueue.Enqueue(item);
}
// 激活扫描中止的线程(发出信号)
AutoReset.Set();
}
复制代码
// 写入日志
private static void WriteLog()
{
var list = new List<Message>();
while (true)
{
// 若是队列中有数据
if (LogQueue.Count() > 0)
{
IT2ESBMessage _msg;
// 出队列
LogQueue.TryDequeue(out _msg);
if (_msg!=null)
{
list.Add(_msg);
}
}
else
{
if (list.Count>0)
{
// 加锁,在多线程操做的时候,保证安全
lock (SyncRoot)
{
foreach (var item in list)
{
ProcessWriteLog(item);
}
}
ist.Clear();
}
// 在这里,线程会被暂停,直到收到信号;
AutoReset.WaitOne();
}
}
}
复制代码
// 写文件
private static void ProcessWriteLog(Message msg)
{
try
{
FileStream fs;
fs = new FileStream(_fileName, FileMode.Append, FileAccess.Write);
//TODO,进行对文件的写操做,省略一万字
}
catch (Exception ex)
{
Debug.WriteLine(string.Format("写入日志失败,缘由:{0}", ex.Message));
}
}
复制代码
AutoResetEvent 关键字多线程
Reset ():将事件状态设置为非终止状态,致使线程阻止;并发
Set ():发送信号到等待线程以继续其工做;函数
有点相似于计算机中的信号量,回顾《操做系统》中的信号量吧,什么银行家算法,什么信号量已经忘得一干二净了。高并发
信号量 用在多线程多任务同步的,一个线程完成了某一个动做就经过信号量告诉别的线程,别的线程再进行某些动做。ui
互斥锁 是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就没法访问,直到这个线程unlock,其余的线程才开始能够利用这个资源spa