美文网首页.NET
简易版StringBuilder对象池

简易版StringBuilder对象池

作者: 冰麟轻武 | 来源:发表于2018-09-01 14:23 被阅读38次

    一、

    StringBuilder对象在程序中经常被用到,一般是希望在拼接字符串时获得更好的性能;
    但是重复构造StringBuilder对象本身也有性能损失,于是有了StringBuilder对象池

    二、

    1. 对象池模型创建并拥有固定数量的对象,当程序需要一个新的对象时,如果对象池中有空闲对象,则立即返回,否则才创建新的该类对象。
    2. 当一个对象不再被使用时,其应该应该将其放回对象池,以便后来的程序使用。由于系统资源有限,一个对象池模型应该指定其可容纳的最大对象数量。
    3. 当达到该数量时,如果仍然有对象创建请求,则抛出异常或者阻塞当前调用线程,直到一个对象被放回对象池中。

    网上抄的

    三、

    基本思路:

    1. 使用ConcurrentQueue<,>保证并发
    2. 利用using语法糖回收对象
    3. 使用Interlocked.Increment计数(Queue中的对象会被取出,不能直接用Length计数)
    4. 当超过最大值时,不抛异常,直接创建一个新的对象,但也不回收该对象

    四、

    /// <summary>
    /// <seealso cref="StringBuilder"/>对象池
    /// </summary>
    static class StringBuilderPool
    {
        /// <summary>
        /// 对象池最大容量大小
        /// </summary>
        public const int MAX_CAPACITY = 63;
        // 对象缓存
        private static readonly ConcurrentQueue<StringBuilder> _cache = new ConcurrentQueue<StringBuilder>();
        // 计数器
        private static int _counter = 0;
        /// <summary>
        /// 弹出 <seealso cref="StringBuilder"/> 对象
        /// </summary>
        public static IDisposable Pop(out StringBuilder builder)
        {
            // 尝试从缓存中获取对象
            _cache.TryDequeue(out builder);
            if (builder != null)
            {
                return new Recyclable(builder); // 返回可回收对象
            }
    
            // 计数器超过池最大容量,或计数器+1超过池最大容量,则直接返回新的 StringBuilder 且不回收
            if (_counter > MAX_CAPACITY || Interlocked.Increment(ref _counter) > MAX_CAPACITY)
            {
                builder = new StringBuilder();
                return NoRecycle; //不回收
            }
            builder = new StringBuilder();
            return new Recyclable(builder);
        }
    
        // 不执行回收操作的空对象
        private static readonly IDisposable NoRecycle = new Recyclable(null);
    
        /// <summary>
        /// 可回收 <seealso cref="StringBuilder"/> 的对象
        /// </summary>
        class Recyclable : IDisposable
        {
            /// <summary>
            /// 初始化对象
            /// </summary>
            /// <param name="builder">待回收的 <seealso cref="StringBuilder"/> 对象</param>
            public Recyclable(StringBuilder builder) => _stringBuilder = builder;
            // 待回收的对象
            private StringBuilder _stringBuilder;
            /// <summary>
            /// 回收对象
            /// </summary>
            public void Dispose()
            {
                // 将 _stringBuilder 修改为null 并返回 _stringBuilder 的原始值
                var builder = Interlocked.Exchange(ref _stringBuilder, null);
                if (builder != null)
                {
                    builder.Clear();
                    _cache.Enqueue(builder); //回收
                }
            }
            // 析构函数
            ~Recyclable() => Dispose();
        }
    }
    

    五、

    调用

    using (StringBuilderPool.Pop(out var builder))
    {
        for (var i = 0; i < 10; i++)
        {
            builder.Append(i);
            builder.AppendLine(",");
        }
        return builder.ToString();
    }
    

    相关文章

      网友评论

        本文标题:简易版StringBuilder对象池

        本文链接:https://www.haomeiwen.com/subject/uxxuwftx.html