一奏夫、
StringBuilder
對象在程序中經常被用到不铆,一般是希望在拼接字符串時獲得更好的性能;
但是重復構造StringBuilder
對象本身也有性能損失泛源,于是有了StringBuilder對象池
二简识、
- 對象池模型創(chuàng)建并擁有固定數(shù)量的對象赶掖,當程序需要一個新的對象時,如果對象池中有空閑對象七扰,則立即返回奢赂,否則才創(chuàng)建新的該類對象。
- 當一個對象不再被使用時戳寸,其應該應該將其放回對象池呈驶,以便后來的程序使用。由于系統(tǒng)資源有限疫鹊,一個對象池模型應該指定其可容納的最大對象數(shù)量袖瞻。
- 當達到該數(shù)量時司致,如果仍然有對象創(chuàng)建請求,則拋出異沉或者阻塞當前調用線程脂矫,直到一個對象被放回對象池中。
網上抄的
三霉晕、
基本思路:
- 使用
ConcurrentQueue<,>
保證并發(fā) - 利用
using
語法糖回收對象 - 使用
Interlocked.Increment
計數(shù)(Queue
中的對象會被取出庭再,不能直接用Length
計數(shù)) - 當超過最大值時,不拋異常牺堰,直接創(chuàng)建一個新的對象拄轻,但也不回收該對象
四、
/// <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>();
// 計數(shù)器
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); // 返回可回收對象
}
// 計數(shù)器超過池最大容量,或計數(shù)器+1超過池最大容量,則直接返回新的 StringBuilder 且不回收
if (_counter > MAX_CAPACITY || Interlocked.Increment(ref _counter) > MAX_CAPACITY)
{
builder = new StringBuilder();
return NoRecycle; //不回收
}
builder = new StringBuilder();
return new Recyclable(builder);
}
// 不執(zhí)行回收操作的空對象
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); //回收
}
}
// 析構函數(shù)
~Recyclable() => Dispose();
}
}
五伟葫、
調用
using (StringBuilderPool.Pop(out var builder))
{
for (var i = 0; i < 10; i++)
{
builder.Append(i);
builder.AppendLine(",");
}
return builder.ToString();
}