对象池模式,对象被预先创建并初始化后放入对象池中,对象提供者,对象提供者就能利用已有的对象来处理请求,减少对象频繁创建所浪费的资源。例如数据库的连接池等等,基本都是创建后就被放入连接池中,后续的查询请求使用的都是连接池中的对象,从而加快了查询速度(不然每次查询都需要重新创建数据库连接对象,比较浪费)。
一句话解释,对象池模式下,程序在一开始就创建好了一批可用对象供使用
这种模式下,一般有两种角色,即对象池管理者和对象池用户。
对象池管理者负责管理整个对象池,包括初始化对象池,扩充对象池的大小,重置归还对象的状态等等。
对象池用户负责从对象池中获取一个对象,用完之后一般需要归还整这个对象。
一般被放入对象池中的对象包括Socket对象,数据库连接对象(连接池),线程对象(线程池)等等。
来看看对象池模式的五大要素:
什么时候使用对象池?
对象池模式的相关对象包括 - 对象池具体结构、池中对象抽象接口、池中对象具体结构、客户:
iPoolObject.go是池中对象抽象接口iPoolObject的代码:
connection.go是池中对象具体结构connection的代码:
pool.go是对象池具体结构pool的代码:
main.go是客户的代码:
结果:
Loan Pool Object with ID: 0
Loan Pool Object with ID: 1
Return Pool Object with ID: 0
Return Pool Object with ID: 1
Go语言内部有sync.pool
包实现了对象池的概念,但是这个设计出来的目的是优化GC的,因为它存储的对象随时都有可能被GC回收掉,具体感兴趣地可以去了解一下该包的用法,这篇文章就不对该包作详细解答了,因为我们的主要目的还是了解对象池模式。因此下面我们会自己实现一个对象池。
当前的场景是我们需要实现一个协程池,我们开始给这个协程池固定一个协程数量,每个协程被用于去执行一项任务(Task),假设当前有1万个任务,我们必不可能用只用一个协程去执行,我们开启若干个协程去不断地轮询执行这些任务
object_pool.go
:
package objectPool
import (
"fmt"
"sync"
"testing"
"time"
)
func TestObjectPool(t *testing.T) {
// 创建一个拥有10个worker的协程池
start := time.Now()
defer func() {
end := time.Now()
fmt.Printf("it takes %f seconds\n",end.Sub(start).Seconds())
}()
wg := &sync.WaitGroup{}
p := NewPool(10,wg)
go p.Run()
// 创建100个task
for i := 0; i < 100; i++ {
wg.Add(1)
t := NewTask(func() error {
// 为了显示出协程池的效果,这里每个任务sleep一秒
time.Sleep(time.Second)
return nil
},i)
p.SetTask(t)
}
wg.Wait()
p.Stop()
}
object_pool_test.go
:
package objectPool
import (
"fmt"
"sync"
"testing"
"time"
)
func TestObjectPool(t *testing.T) {
// 创建一个拥有10个worker的协程池
start := time.Now()
defer func() {
end := time.Now()
fmt.Printf("it takes %f seconds\n",end.Sub(start).Seconds())
}()
wg := &sync.WaitGroup{}
p := NewPool(10,wg)
go p.Run()
// 创建100个task
for i := 0; i < 100; i++ {
wg.Add(1)
t := NewTask(func() error {
// 为了显示出协程池的效果,这里每个任务sleep一秒
time.Sleep(time.Second)
return nil
},i)
p.SetTask(t)
}
wg.Wait()
p.Stop()
}
结果:
=== RUN TestObjectPool
workerID: 8, the task id 8 was successfully executed
workerID: 2, the task id 4 was successfully executed
...............
...............
workerID: 6, the task id 2 was successfully executed
workerID: 6, the task id 97 was successfully executed
workerID: 2, the task id 99 was successfully executed
it takes 10.030659 seconds
--- PASS: TestObjectPool (10.03s)
PASS
参考资料:
Go实现设计模式系列(8)——Go实现对象池模式
https://blog.csdn.net/lvyibin890/article/details/107765752
go 初始化对象_Go语言设计模式-对象池
https://blog.csdn.net/weixin_42438750/article/details/112099758