Go设计模式-对象池模式

133 阅读1分钟

什么是对象池模式

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
}