/// <summary>
/// 对象池
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool<T>
{
private readonly ConcurrentBag<T> _buffer;
private readonly Func<T> _createFunc;
private readonly Action<T> _resetFunc;
public int Capacity { get; private set; }
private readonly int _chunkSize;
public int Count { get { return _buffer.Count; } }
public ObjectPool(Func<T> createFunc, Action<T> resetFunc, int capacity = 50, int chunkSize = 10)
{
if (createFunc == null)
{
throw new ArgumentNullException("createFunc");
}
if (capacity <= 0)
{
throw new ArgumentOutOfRangeException("capacity");
}
if (chunkSize <= 0)
{
throw new ArgumentOutOfRangeException("chunkSize");
}
this._buffer = new ConcurrentBag<T>();
this._createFunc = createFunc;
this._resetFunc = resetFunc;
this.Capacity = capacity;
this._chunkSize = chunkSize;
AllocateChunk();
}
public T GetObject()
{
T obj;
if (!_buffer.TryTake(out obj))
{
//创建一些数据
AllocateChunk();
_buffer.TryTake(out obj);
}
return obj;
}
public void ReleaseObject(T obj)
{
Contract.Assume(obj != null);
//超过容量了,不再需要
if (Count >= Capacity) return;
if (_resetFunc != null)
{
_resetFunc(obj);
}
_buffer.Add(obj);
}
private void AllocateChunk()
{
for (int i = 0; i < _chunkSize; i++)
{
_buffer.Add(_createFunc());
}
}
}
class Program
{
staticvoid Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
// Create an opportunity for the user to cancel.
Task.Run(() =>
{
if (Console.ReadKey().KeyChar == 'c' || Console.ReadKey().KeyChar == 'C')
cts.Cancel();
});
ObjectPool<MyClass> pool = new ObjectPool<MyClass> (() => new MyClass());
// Create a high demand for MyClass objects.
Parallel.For(0, 1000000, (i, loopState) =>
{
MyClass mc = pool.GetObject();
Console.CursorLeft = 0;
// This is the bottleneck in our application. All threads in this loop// must serialize their access to the static Console class.
Console.WriteLine("{0:####.####}", mc.GetValue(i));
pool.PutObject(mc);
if (cts.Token.IsCancellationRequested)
loopState.Stop();
});
Console.WriteLine("Press the Enter key to exit.");
Console.ReadLine();
cts.Dispose();
}
}