/// <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(); } }