设计模式之美:Object Pool(对象池)
索引
意图
运用对象池化技术可以显著地提升性能,尤其是当对象的初始化过程代价较大或者频率较高时。
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 对象。
namespace ObjectPoolPattern.Implementation1
{
public abstract class ObjectPool<T>
{
private TimeSpan _expirationTime;
private Dictionary<T, DateTime> _unlocked;
private Dictionary<T, DateTime> _locked;
private readonly object _sync = new object(); public ObjectPool()
{
_expirationTime = TimeSpan.FromSeconds();
_locked = new Dictionary<T, DateTime>();
_unlocked = new Dictionary<T, DateTime>();
} public ObjectPool(TimeSpan expirationTime)
: this()
{
_expirationTime = expirationTime;
} protected abstract T Create(); public abstract bool Validate(T reusable); public abstract void Expire(T reusable); public T CheckOut()
{
lock (_sync)
{
T reusable = default(T); if (_unlocked.Count > )
{
foreach (var item in _unlocked)
{
if ((DateTime.UtcNow - item.Value) > _expirationTime)
{
// object has expired
_unlocked.Remove(item.Key);
Expire(item.Key);
}
else
{
if (Validate(item.Key))
{
// find a reusable object
_unlocked.Remove(item.Key);
_locked.Add(item.Key, DateTime.UtcNow);
reusable = item.Key;
break;
}
else
{
// object failed validation
_unlocked.Remove(item.Key);
Expire(item.Key);
}
}
}
} // no object available, create a new one
if (reusable == null)
{
reusable = Create();
_locked.Add(reusable, DateTime.UtcNow);
} return reusable;
}
} public void CheckIn(T reusable)
{
lock (_sync)
{
_locked.Remove(reusable);
_unlocked.Add(reusable, DateTime.UtcNow);
}
}
} public class DatabaseConnection : IDisposable
{
// do some heavy works
public DatabaseConnection(string connectionString)
{
} public bool IsOpen { get; set; } // release something
public void Dispose()
{
}
} public class DatabaseConnectionPool : ObjectPool<DatabaseConnection>
{
private string _connectionString; public DatabaseConnectionPool(string connectionString)
: base(TimeSpan.FromMinutes())
{
this._connectionString = connectionString;
} protected override DatabaseConnection Create()
{
return new DatabaseConnection(_connectionString);
} public override void Expire(DatabaseConnection connection)
{
connection.Dispose();
} public override bool Validate(DatabaseConnection connection)
{
return connection.IsOpen;
}
} public class Client
{
public static void TestCase1()
{
// Create the ConnectionPool:
DatabaseConnectionPool pool = new DatabaseConnectionPool(
"Data Source=DENNIS;Initial Catalog=TESTDB;Integrated Security=True;"); // Get a connection:
DatabaseConnection connection = pool.CheckOut(); // Use the connection // Return the connection:
pool.CheckIn(connection);
}
}
}
实现方式(二):使用对象构造方法和预分配方式实现 ObjectPool 类。
namespace ObjectPoolPattern.Implementation2
{
/// <summary>
/// 对象池
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public class ObjectPool<T> where T : class
{
private readonly Func<T> _objectFactory;
private readonly ConcurrentQueue<T> _queue = new ConcurrentQueue<T>(); /// <summary>
/// 对象池
/// </summary>
/// <param name="objectFactory">构造缓存对象的函数</param>
public ObjectPool(Func<T> objectFactory)
{
_objectFactory = objectFactory;
} /// <summary>
/// 构造指定数量的对象
/// </summary>
/// <param name="count">数量</param>
public void Allocate(int count)
{
for (int i = ; i < count; i++)
_queue.Enqueue(_objectFactory());
} /// <summary>
/// 缓存一个对象
/// </summary>
/// <param name="obj">对象</param>
public void Enqueue(T obj)
{
_queue.Enqueue(obj);
} /// <summary>
/// 获取一个对象
/// </summary>
/// <returns>对象</returns>
public T Dequeue()
{
T obj;
return !_queue.TryDequeue(out obj) ? _objectFactory() : obj;
}
} class Program
{
static void Main(string[] args)
{
var pool = new ObjectPool<byte[]>(() => new byte[]);
pool.Allocate(); var buffer = pool.Dequeue(); // .. do something here .. pool.Enqueue(buffer);
}
}
}
《设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。
设计模式之美:Object Pool(对象池)的更多相关文章
- Object Pool 对象池的C++11使用(转)
很多系统对资源的访问快捷性及可预测性有严格要求,列入包括网络连接.对象实例.线程和内存.而且还要求解决方案可扩展,能应付存在大量资源的情形. object pool针对特定类型的对象循环利用,这些对象 ...
- JedisCluster中应用的Apache Commons Pool对象池技术
对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分. apache common pool 官方文档可以参考:https://c ...
- Object Pooling(对象池)实现
在文章开始之前首先要思考的问题是为什么要建立对象池.这和.NET垃圾回收机制有关,正如下面引用所说,内存不是无限的,垃圾回收器最终要回收对象,释放内存.尽管.NET为垃圾回收已经进行了大量优化,例如将 ...
- .NET Core中Object Pool的简单使用
前言 复用,是一个重要的话题,也是我们日常开发中经常遇到的,不可避免的问题. 举个最为简单,大家最为熟悉的例子,数据库连接池,就是复用数据库连接. 那么复用的意义在那里呢? 简单来说就是减少不必要的资 ...
- java对象池化技术
https://blog.csdn.net/tiane5hao/article/details/85957840 文章目录 先写一个简单通用的对象池 通过上面的通用池实现jedis连接池 连接池测试 ...
- 缓冲&缓存&对象池概念的理解
一).缓冲 作用:缓解程序上下层之间的性能差异. 1).当上层组件的性能优于下层组件时加入缓冲机制可以减少上层组件对下 层组件的等待时间. 2).上层组件不需要等待下层组件接收全部数据,即可返回操作, ...
- Java堆外内存之一:堆外内存场景介绍(对象池VS堆外内存)
最近经常有人问我在Java中使用堆外(off heap)内存的好处与用途何在.我想其他面临几样选择的人应该也会对这个答案感兴趣吧. 堆外内存其实并无特别之处.线程栈,应用程序代码,NIO缓存用的都是堆 ...
- Unity实现简单的对象池
一.简介 先说说为什么要使用对象池 在Unity游戏运行时,经常需要生成一些物体,例如子弹.敌人等.虽然Unity中有Instantiate()方法可以使用,但是在某些情况下并不高效.特别是对于那些需 ...
- [译]Unity3D内存管理——对象池(Object Pool)
原文地址:C# Memory Management for Unity Developers (part 3 of 3), 其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身 ...
随机推荐
- 强大的Spring缓存技术(上)
缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 cache 配置方法,展现了 ...
- 什么是publickeytoken及publickeytoken的作用
什么是publickeytoken及publickeytoken的作用 dll的publickeytoken的作用.
- js数组方法push pop shift unshift的返回值
push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度. pop() 方法用于删除并返回数组的最后一个元素. unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度. s ...
- mysql 行变列(多行变成一行/多行合并成一行/多行合并成多列/合并行)
数据库结构如图: 而我想让同一个人的不同成绩变成此人在这一行不同列上显示出来,此时分为2中展现: 第一种展现如图----[多行变一列](合并后的数据在同一列上): sql如下: select name ...
- Memcached Memcached.ClientLibrary.SockIOPool”的类型初始值设定项引发异常
又一次遭遇"xxx类型初始值设定项引发异常" 下了个c#实现的轻量级IoC开源项目,可是在本地使用时发现一运行就捕捉到"类型初始值设定项引发异常"的异常信息,调 ...
- AngularJS四大特性
Google AnguarJS是一个JS框架,适用于以数据的CRUD操作为主的SPA应用. 四大特性: (1)MVC模型 Model:模型,即数据=>JS中的变量 View:视图,即数据的呈现= ...
- Maven仓库管理-Nexus
Maven仓库管理-Nexus @import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style& ...
- 也说说angularJs里的evalAsync
虽说angular都快出2.0了,到了2.0这些东东都会被干掉.不过我们眼前的事还是要处理. $evalAsync和$timeout到底什么区别,网上说法很多,最近看到的是说在directive里就怎 ...
- python基础第三天(1)
函数 函数分为:内置函数,自定义函数,导入函数. 内置函数 python为咱们提供的快捷方式 vars()---针对脚本的,找到这个脚本中的所有变量. #!/usr/bin/env python # ...
- python ImportError: DLL load failed: %1 不是有效的 Win32 应用程序
导入的时候报出了 ImportError 在windows上安装python 的模块后,导入模块时报 python ImportError: DLL load failed: %1 不是有效的 Win ...