Skip to main content

对象池模式

code

package main

import (
"fmt"
"log"
"strconv"
"sync"
)

type iPoolObject interface {
getID() string //This is any id which can be used to compare two different pool objects
}

type pool struct {
idle []iPoolObject
active []iPoolObject
capacity int
mulock *sync.Mutex
}

//InitPool Initialize the pool
func initPool(poolObjects []iPoolObject) (*pool, error) {
if len(poolObjects) == 0 {
return nil, fmt.Errorf("Cannot craete a pool of 0 length")
}
active := make([]iPoolObject, 0)
pool := &pool{
idle: poolObjects,
active: active,
capacity: len(poolObjects),
mulock: new(sync.Mutex),
}
return pool, nil
}

func (p *pool) loan() (iPoolObject, error) {
p.mulock.Lock()
defer p.mulock.Unlock()
if len(p.idle) == 0 {
return nil, fmt.Errorf("No pool object free. Please request after sometime")
}
obj := p.idle[0]
p.idle = p.idle[1:]
p.active = append(p.active, obj)
fmt.Printf("Loan Pool Object with ID: %s\n", obj.getID())
return obj, nil
}

func (p *pool) receive(target iPoolObject) error {
p.mulock.Lock()
defer p.mulock.Unlock()
err := p.remove(target)
if err != nil {
return err
}
p.idle = append(p.idle, target)
fmt.Printf("Return Pool Object with ID: %s\n", target.getID())
return nil
}

func (p *pool) remove(target iPoolObject) error {
currentActiveLength := len(p.active)
for i, obj := range p.active {
if obj.getID() == target.getID() {
// 这里将target与最后一个调换
p.active[currentActiveLength-1], p.active[i] = p.active[i], p.active[currentActiveLength-1]
// 将最后一个移除
p.active = p.active[:currentActiveLength-1]
return nil
}
}
return fmt.Errorf("Targe pool object doesn't belong to the pool")
}

type connection struct {
id string
}

func (c *connection) getID() string {
return c.id
}

func main() {
connections := make([]iPoolObject, 0)
for i := 0; i < 3; i++ {
c := &connection{id: strconv.Itoa(i)}
connections = append(connections, c)
}
pool, err := initPool(connections)
if err != nil {
log.Fatalf("Init Pool Error: %s", err)
}
conn1, err := pool.loan()
if err != nil {
log.Fatalf("Pool Loan Error: %s", err)
}
conn2, err := pool.loan()
if err != nil {
log.Fatalf("Pool Loan Error: %s", err)
}
pool.receive(conn1)
pool.receive(conn2)
}

解释

在这个代码中实现的是一种对象池(Object Pool)设计模式。对象池是一种创建型设计模式,旨在通过重用对象来减少创建和销毁对象的开销,从而提高性能。

关键点

  1. 池的初始化:

    • initPool 函数用于初始化对象池,接收一个对象列表作为参数。
  2. 借出对象:

    • loan 方法从空闲对象列表中借出一个对象,将其移到活跃对象列表中。
  3. 归还对象:

    • receive 方法用于将对象归还到空闲对象列表,并从活跃对象列表中移除。
  4. 线程安全:

    • 使用 sync.Mutex 确保对池操作的线程安全。

优点

  • 性能提升: 通过重用对象,减少了对象的创建和销毁次数。
  • 资源管理: 控制对象的数量,避免资源耗尽。

使用场景

  • 适用于需要频繁创建和销毁对象的场景,如数据库连接、线程池等。

虽然实现上看似简单,但它有效地管理了对象的生命周期和状态,避免了不必要的资源浪费。