索引
運用對象池化技術可以顯著地提升性能,尤其是當對象的初始化過程代價較大或者頻率較高時。
Object pooling can offer a significant performance boost; it is most effective in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high.
Reusable
- 類的實例與其他對象進行有限時間的交互。
ReusablePool
- 管理類的實例。
Client
- 使用類的實例。
當以下情況成立時可以使用 Object Pool 模式:
- 類的實例可重用於交互。
- 類的實例化過程開銷較大。
- 類的實例化的頻率較高。
- 類參與交互的時間周期有限。
- 節省了創建類的實例的開銷。
- 節省了創建類的實例的時間。
- 存儲空間隨着對象的增多而增大。
- 通常,可以使用 Singleton 模式實現 ReusablePool 類。
- Factory Method 模式封裝了對象的創建的過程,但其不負責管理對象。Object Pool 負責管理對象。
實現方式(一):實現 DatabaseConnectionPool 類。
如果 Client 調用 ObjectPool 的 AcquireReusable() 方法來獲取 Reusable 對象,當在 ObjectPool 中存在可用的 Reusable 對象時,其將一個 Reusable 從池中移除,然后返回該對象。如果池為空,則 ObjectPool 會創建一個新的 Reusable 對象。
1 namespace ObjectPoolPattern.Implementation1 2 { 3 public abstract class ObjectPool<T> 4 { 5 private TimeSpan _expirationTime; 6 private Dictionary<T, DateTime> _unlocked; 7 private Dictionary<T, DateTime> _locked; 8 private readonly object _sync = new object(); 9 10 public ObjectPool() 11 { 12 _expirationTime = TimeSpan.FromSeconds(30); 13 _locked = new Dictionary<T, DateTime>(); 14 _unlocked = new Dictionary<T, DateTime>(); 15 } 16 17 public ObjectPool(TimeSpan expirationTime) 18 : this() 19 { 20 _expirationTime = expirationTime; 21 } 22 23 protected abstract T Create(); 24 25 public abstract bool Validate(T reusable); 26 27 public abstract void Expire(T reusable); 28 29 public T CheckOut() 30 { 31 lock (_sync) 32 { 33 T reusable = default(T); 34 35 if (_unlocked.Count > 0) 36 { 37 foreach (var item in _unlocked) 38 { 39 if ((DateTime.UtcNow - item.Value) > _expirationTime) 40 { 41 // object has expired 42 _unlocked.Remove(item.Key); 43 Expire(item.Key); 44 } 45 else 46 { 47 if (Validate(item.Key)) 48 { 49 // find a reusable object 50 _unlocked.Remove(item.Key); 51 _locked.Add(item.Key, DateTime.UtcNow); 52 reusable = item.Key; 53 break; 54 } 55 else 56 { 57 // object failed validation 58 _unlocked.Remove(item.Key); 59 Expire(item.Key); 60 } 61 } 62 } 63 } 64 65 // no object available, create a new one 66 if (reusable == null) 67 { 68 reusable = Create(); 69 _locked.Add(reusable, DateTime.UtcNow); 70 } 71 72 return reusable; 73 } 74 } 75 76 public void CheckIn(T reusable) 77 { 78 lock (_sync) 79 { 80 _locked.Remove(reusable); 81 _unlocked.Add(reusable, DateTime.UtcNow); 82 } 83 } 84 } 85 86 public class DatabaseConnection : IDisposable 87 { 88 // do some heavy works 89 public DatabaseConnection(string connectionString) 90 { 91 } 92 93 public bool IsOpen { get; set; } 94 95 // release something 96 public void Dispose() 97 { 98 } 99 } 100 101 public class DatabaseConnectionPool : ObjectPool<DatabaseConnection> 102 { 103 private string _connectionString; 104 105 public DatabaseConnectionPool(string connectionString) 106 : base(TimeSpan.FromMinutes(1)) 107 { 108 this._connectionString = connectionString; 109 } 110 111 protected override DatabaseConnection Create() 112 { 113 return new DatabaseConnection(_connectionString); 114 } 115 116 public override void Expire(DatabaseConnection connection) 117 { 118 connection.Dispose(); 119 } 120 121 public override bool Validate(DatabaseConnection connection) 122 { 123 return connection.IsOpen; 124 } 125 } 126 127 public class Client 128 { 129 public static void TestCase1() 130 { 131 // Create the ConnectionPool: 132 DatabaseConnectionPool pool = new DatabaseConnectionPool( 133 "Data Source=DENNIS;Initial Catalog=TESTDB;Integrated Security=True;"); 134 135 // Get a connection: 136 DatabaseConnection connection = pool.CheckOut(); 137 138 // Use the connection 139 140 // Return the connection: 141 pool.CheckIn(connection); 142 } 143 } 144 }
實現方式(二):使用對象構造方法和預分配方式實現 ObjectPool 類。
1 namespace ObjectPoolPattern.Implementation2 2 { 3 /// <summary> 4 /// 對象池 5 /// </summary> 6 /// <typeparam name="T">對象類型</typeparam> 7 public class ObjectPool<T> where T : class 8 { 9 private readonly Func<T> _objectFactory; 10 private readonly ConcurrentQueue<T> _queue = new ConcurrentQueue<T>(); 11 12 /// <summary> 13 /// 對象池 14 /// </summary> 15 /// <param name="objectFactory">構造緩存對象的函數</param> 16 public ObjectPool(Func<T> objectFactory) 17 { 18 _objectFactory = objectFactory; 19 } 20 21 /// <summary> 22 /// 構造指定數量的對象 23 /// </summary> 24 /// <param name="count">數量</param> 25 public void Allocate(int count) 26 { 27 for (int i = 0; i < count; i++) 28 _queue.Enqueue(_objectFactory()); 29 } 30 31 /// <summary> 32 /// 緩存一個對象 33 /// </summary> 34 /// <param name="obj">對象</param> 35 public void Enqueue(T obj) 36 { 37 _queue.Enqueue(obj); 38 } 39 40 /// <summary> 41 /// 獲取一個對象 42 /// </summary> 43 /// <returns>對象</returns> 44 public T Dequeue() 45 { 46 T obj; 47 return !_queue.TryDequeue(out obj) ? _objectFactory() : obj; 48 } 49 } 50 51 class Program 52 { 53 static void Main(string[] args) 54 { 55 var pool = new ObjectPool<byte[]>(() => new byte[65535]); 56 pool.Allocate(1000); 57 58 var buffer = pool.Dequeue(); 59 60 // .. do something here .. 61 62 pool.Enqueue(buffer); 63 } 64 } 65 }
《設計模式之美》為 Dennis Gao 發布於博客園的系列文章,任何未經作者本人同意的人為或爬蟲轉載均為耍流氓。