zoukankan      html  css  js  c++  java
  • 100多行代码实现6秒完成50万条多线程并发日志文件写入

    该日志工具类代码只是测试用,实际项目不用。这里有个自己平时常用的,每秒可以写入1万条日志以上: https://www.cnblogs.com/s0611163/p/4023859.html

    100多行代码实现6秒完成50万条多线程并发日志文件写入,支持日志文件分隔

    日志工具类代码:

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Utils
    {
        /// <summary>
        /// 写日志类
        /// </summary>
        public class LogUtil
        {
            #region 字段
            public static object _lock = new object();
            public static string path = "D:\log";
            public static int fileSize = 10 * 1024 * 1024; //日志分隔文件大小
            private static ConcurrentQueue<Tuple<string, string>> msgQueue = new ConcurrentQueue<Tuple<string, string>>();
            #endregion
    
            #region 静态构造函数
            static LogUtil()
            {
                Thread thread = new Thread(new ThreadStart(() =>
                {
                    try
                    {
                        int i;
                        List<string> list;
                        Tuple<string, string> tuple;
    
                        while (true)
                        {
                            i = 0;
                            list = new List<string>();
                            while (msgQueue.TryDequeue(out tuple) && i++ < 10000)
                            {
                                list.Add(tuple.Item1.PadLeft(8) + tuple.Item2);
                            }
                            if (list.Count > 0)
                            {
                                WriteFile(list, CreateLogPath());
                            }
    
                            Thread.Sleep(1);
                        }
                    }
                    catch
                    {
    
                    }
                }));
                thread.IsBackground = true;
                thread.Start();
            }
            #endregion
    
            #region 写文件
            /// <summary>
            /// 写文件
            /// </summary>
            public static void WriteFile(List<string> list, string path)
            {
                try
                {
                    if (!Directory.Exists(Path.GetDirectoryName(path)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(path));
                    }
    
                    if (!File.Exists(path))
                    {
                        using (FileStream fs = new FileStream(path, FileMode.Create)) { fs.Close(); }
                    }
    
                    using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
                    {
                        using (StreamWriter sw = new StreamWriter(fs))
                        {
                            list.ForEach(item =>
                            {
                                #region 日志内容
                                string value = string.Format(@"{0} {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), item);
                                #endregion
    
                                sw.WriteLine(value);
                            });
    
                            sw.Flush();
                        }
                        fs.Close();
                    }
                }
                catch { }
            }
            #endregion
    
            #region 生成日志文件路径
            /// <summary>
            /// 生成日志文件路径
            /// </summary>
            public static string CreateLogPath()
            {
                int index = 0;
                string logPath;
                bool bl = true;
                do
                {
                    index++;
                    logPath = Path.Combine(path, "Log" + DateTime.Now.ToString("yyyyMMdd") + (index == 1 ? "" : "_" + index.ToString()) + ".txt");
                    if (File.Exists(logPath))
                    {
                        FileInfo fileInfo = new FileInfo(logPath);
                        if (fileInfo.Length < fileSize)
                        {
                            bl = false;
                        }
                    }
                    else
                    {
                        bl = false;
                    }
                } while (bl);
    
                return logPath;
            }
            #endregion
    
            #region 写错误日志
            /// <summary>
            /// 写错误日志
            /// </summary>
            public static void LogError(string log)
            {
                msgQueue.Enqueue(new Tuple<string, string>("[Error] ", log));
            }
            #endregion
    
            #region 写操作日志
            /// <summary>
            /// 写操作日志
            /// </summary>
            public static void Log(string log)
            {
                msgQueue.Enqueue(new Tuple<string, string>("[Info]  ", log));
            }
            #endregion
    
        }
    }
    View Code

    使用条件变量模式改进:

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Utils
    {
        /// <summary>
        /// 写日志类
        /// </summary>
        public class LogUtil
        {
            #region 字段
            public static object _lock = new object();
            public static string path = "D:\log";
            public static int fileSize = 10 * 1024 * 1024; //日志分隔文件大小
            private static ConcurrentQueue<Tuple<string, string>> msgQueue = new ConcurrentQueue<Tuple<string, string>>();
            #endregion
    
            #region 静态构造函数
            static LogUtil()
            {
                Thread thread = new Thread(new ThreadStart(() =>
                {
                    try
                    {
                        Monitor.Enter(_lock);
                        int i;
                        List<string> list;
                        Tuple<string, string> tuple;
    
                        while (true)
                        {
                            Monitor.Wait(_lock);
    
                            i = 0;
                            list = new List<string>();
                            while (msgQueue.TryDequeue(out tuple) && i++ < 10000)
                            {
                                list.Add(tuple.Item1.PadLeft(8) + tuple.Item2);
                            }
                            if (list.Count > 0)
                            {
                                WriteFile(list, CreateLogPath());
                            }
                        }
                    }
                    catch
                    {
    
                    }
                }));
                thread.IsBackground = true;
                thread.Start();
            }
            #endregion
    
            #region 写文件
            /// <summary>
            /// 写文件
            /// </summary>
            public static void WriteFile(List<string> list, string path)
            {
                try
                {
                    if (!Directory.Exists(Path.GetDirectoryName(path)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(path));
                    }
    
                    if (!File.Exists(path))
                    {
                        using (FileStream fs = new FileStream(path, FileMode.Create)) { fs.Close(); }
                    }
    
                    using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
                    {
                        using (StreamWriter sw = new StreamWriter(fs))
                        {
                            list.ForEach(item =>
                            {
                                #region 日志内容
                                string value = string.Format(@"{0} {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), item);
                                #endregion
    
                                sw.WriteLine(value);
                            });
    
                            sw.Flush();
                        }
                        fs.Close();
                    }
                }
                catch { }
            }
            #endregion
    
            #region 生成日志文件路径
            /// <summary>
            /// 生成日志文件路径
            /// </summary>
            public static string CreateLogPath()
            {
                int index = 0;
                string logPath;
                bool bl = true;
                do
                {
                    index++;
                    logPath = Path.Combine(path, "Log" + DateTime.Now.ToString("yyyyMMdd") + (index == 1 ? "" : "_" + index.ToString()) + ".txt");
                    if (File.Exists(logPath))
                    {
                        FileInfo fileInfo = new FileInfo(logPath);
                        if (fileInfo.Length < fileSize)
                        {
                            bl = false;
                        }
                    }
                    else
                    {
                        bl = false;
                    }
                } while (bl);
    
                return logPath;
            }
            #endregion
    
            #region 写错误日志
            /// <summary>
            /// 写错误日志
            /// </summary>
            public static void LogError(string log)
            {
                msgQueue.Enqueue(new Tuple<string, string>("[Error] ", log));
                Task.Factory.StartNew(() =>
                {
                    Monitor.Enter(_lock);
                    Monitor.PulseAll(_lock);
                    Monitor.Exit(_lock);
                });
            }
            #endregion
    
            #region 写操作日志
            /// <summary>
            /// 写操作日志
            /// </summary>
            public static void Log(string log)
            {
                msgQueue.Enqueue(new Tuple<string, string>("[Info]  ", log));
                Task.Factory.StartNew(() =>
                {
                    Monitor.Enter(_lock);
                    Monitor.PulseAll(_lock);
                    Monitor.Exit(_lock);
                });
            }
            #endregion
    
        }
    }
    View Code

    测试代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Utils;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                LogUtil.path = Application.StartupPath + "\log"; //初始化日志路径
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                for (int n = 0; n < 10; n++)
                {
                    Thread thread = new Thread(new ThreadStart(() =>
                    {
                        int i = 0;
                        for (int k = 0; k < 50000; k++)
                        {
                            LogUtil.Log((i++).ToString() + "    abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcda3.1415bcdabcdabcdabcdabc@#$%^&dabcdabcdabcdabcdabcdabcdabcdabcd");
                        }
                    }));
                    thread.IsBackground = true;
                    thread.Start();
                }
            }
        }
    }
    View Code

     测试截图:

  • 相关阅读:
    linux添加开机启动项、登陆启动项、定时启动项、关机执行项等的方法
    linux下/etc/rc.d目录的介绍及redhat启动顺序
    Linux开机自动挂载存储的两种方式
    Linux中环境变量文件profile、bashrc、bash_profile之间的区别和联系
    linux命令详解——yum
    linux命令详解——ftp
    Shell脚本之sed详解
    shell awk读取文件中的指定行的指定字段
    MySQL的字符集
    shell脚本中的数组
  • 原文地址:https://www.cnblogs.com/s0611163/p/7234361.html
Copyright © 2011-2022 走看看