什么是对象池模式
Object pool Pattern, 对象被预先初始化并存储于对象池中,当需要时,客户端可以从对象池中请求一个对象并使用,然后将其返回对象池中
组成:
- 对象池: 类,主要用于维护可用对象的列表和已从对象池中请求的对象集合
- 客户端:调用对象池中被池化的对许
- 可重用池:用于判断对象池是否可重用
使用场景
- 系统资源受限,需要提高内存管理效率
- 需要创建大量的对象
- 当对象是不可变对象
- 短时间内连续创建和销毁大量对象
实现
go中的sync.Pool 实现了对象池,但其目的是为了优化GC, sync.Pool的存储对象随时可能被垃圾回收
- 定义资源以及相关变量,并且初始化资源
//资源类
type Resource struct {
reusable int
}
//初始化资源对象
//模拟缓慢的资源访问,例如,TCP 连接等
func NewResource(id int) *Resource {
time.Sleep(500 * time.Millisecond)
return &Resource{reusable: id}
}
//模拟资源耗时
func (r *Resource) Do(workId int) {
time.Sleep(time.Duration(rand.Intn(5)) * 100 * time.Millisecond)
log.Printf("using resource #%d finished work %d finish\n", r.reusable, workId)
}
- 创建一个指定大小的对象池
//对象池
type Pool chan *Resource
//并发创建资源对象,节省资源对象初始化时间
func New(size int) Pool {
p := make(Pool, size)
wg := new(sync.WaitGroup)
wg.Add(size)
for i := 0; i < size; i++ {
go func(reusable int) {
p <- NewResource(reusable)
wg.Done()
}(i)
}
wg.Wait()
return p
}
- 基于通道获取对象池中的资源对象
//从获取对象池获取对象
func (p Pool) GetResource() (r *Resource, err error) {
select {
case r := <-p:
return r, nil
case <-time.After(getResMaxTime):
return nil, ErrGetResTimeout
}
}
- 将资源返回对象池
//将资源返回到资源池
func (p Pool) GiveBackResource(r *Resource) error {
if p == nil {
return ErrPoolNotExist
}
p <- r
return nil
}