using System.Diagnostics;
//测试
stc s=new stc();
//初始化程序连接池
stc.pool_DataTranfserItem = new ObjectPoolMs<MyObjectTest>(s.CreateDataTranfserItem, 200);
//使用对象池创建对象
MyObjectTest test = stc.pool_DataTranfserItem.Allocate();
MyObjectTest test1 = stc.pool_DataTranfserItem.Allocate();
MyObjectTest test2 = stc.pool_DataTranfserItem.Allocate();
Console.WriteLine( test.Guid);
Console.WriteLine(test1.Guid);
Console.WriteLine(test2.Guid);
//用完的对象回收
stc.pool_DataTranfserItem.Free(test);
stc.pool_DataTranfserItem.Free(test1);
MyObjectTest test3 = stc.pool_DataTranfserItem.Allocate();
MyObjectTest test4 = stc.pool_DataTranfserItem.Allocate();
MyObjectTest test5 = stc.pool_DataTranfserItem.Allocate();
Console.WriteLine(test3.Guid);
Console.WriteLine(test4.Guid);
Console.WriteLine(test5.Guid);
Console.ReadLine();
//要放入对象池的对象
public class stc
{
public MyObjectTest CreateDataTranfserItem()
{
return new MyObjectTest();
}
public static ObjectPoolMs<MyObjectTest> pool_DataTranfserItem = null;
}
//创建对象的池
public class MyObjectTest
{
public Guid Guid { get; set; }=Guid.NewGuid();
public string Name { get; set; }
public int Age { get; set; }
public MyObjectTest()
{
Console.WriteLine("测试");
}
}
public class ObjectPoolMs<T> where T : class
{
[DebuggerDisplay("{Value,nq}")]
private struct Element
{
internal T Value;
}
public delegate T Factory();
//用来接收第一个对象
private T _firstItem;
private readonly Element[] _items;
//泛型委托
private readonly Factory _factory;
public ObjectPoolMs(Factory factory)
: this(factory, Environment.ProcessorCount * 2)
{ }
//初始化 ,要创建的对象,和池的大小
public ObjectPoolMs(Factory factory, int size)
{
Debug.Assert(size >= 1);
_factory = factory;
_items = new Element[size - 1];
}
//创建对象并返回
private T CreateInstance()
{
T inst = _factory();
return inst;
}
/// <summary>
/// 产生一个实例
/// </summary>
/// <remarks>
//搜索策略是一个简单的线性探测,选择它是因为它的缓存友好性。注意,Free会尝试 ///将回收的对象存储在靠近开始的位置,从而从统计上减少我们通常要搜索的距离
/// </remarks>
public T Allocate()
{
//性能:检查第一个元素。如果失败,AllocateFlow将查看剩余的元素。笔记
//乐观地说,初始读取不同步。这是故意的。我们只有在
//我们有一个候选人。在最坏的情况下,我们可能会错过一些最近返回的对象。没什么大不了的。
T inst = _firstItem;
if (inst == null || inst != Interlocked.CompareExchange(ref _firstItem, null, inst))
{
inst = AllocateSlow();
}
return inst;
}
private T AllocateSlow()
{
Element[] items = _items;
for (int i = 0; i < items.Length; i++)
{
//请注意,乐观地说,初始读取是不同步的。这是故意的。我们将互锁
//只有当我们有候选人时。在最坏的情况下,我们可能会错过一些最近返回的对象。没什么大不了的
T inst = items[i].Value;
if (inst != null)
{
if (inst == Interlocked.CompareExchange(ref items[i].Value, null, inst))
{
return inst;
}
}
}
return CreateInstance();
}
///<summary>
///将对象返回到池。
///</summary>
///<备注>
///搜索策略是一种简单的线性探测,它是为缓存友好而选择的。请注意,Free将尝试
///将回收的对象存储在接近开始的位置,从而从统计上减少我们通常在分配中搜索的距离。
///</备注>
public void Free(T obj)
{
Validate(obj);
if (_firstItem == null)
{
//此处无意使用联锁。在最坏的情况下,两个对象可能存储在同一个
//插槽。这不太可能发生,只意味着其中一个对象将被收集。
_firstItem = obj;
}
else
{
FreeSlow(obj);
}
}
private void FreeSlow(T obj)
{
Element[] items = _items;
for (int i = 0; i < items.Length; i++)
{
if (items[i].Value == null)
{
//此处无意使用联锁。在最坏的情况下,可以将两个对象存储到
//同一插槽。这不太可能发生,只意味着其中一个对象将被收集。
items[i].Value = obj;
break;
}
}
}
[Conditional("DEBUG")]
private void Validate(object obj)
{
Debug.Assert(obj != null, "freeing null?");
Debug.Assert(_firstItem != obj, "freeing twice?");
var items = _items;
for (int i = 0; i < items.Length; i++)
{
var value = items[i].Value;
if (value == null)
{
return;
}
Debug.Assert(value != obj, "freeing twice?");
}
}
}
.net 对象链接池创建和使用
最新推荐文章于 2024-07-10 21:37:49 发布