首页 > 代码库 > golang 创建一个简单的资源池,重用资源,减少GC负担
golang 创建一个简单的资源池,重用资源,减少GC负担
package main;import ( "sync" "errors" "fmt")//代码参考《Go语言实战》中第7章并发模式Pool//如果哪个类型实现了Resource接口中的两个方法,我们就认为该类型是资源type Resource interface { Close(); IsClosed() bool;}//工厂方法,用于创建新资源type Factory func() (Resource, error)//资源池type ResourcePool struct { //互斥锁,保证池中资源的安全 mu sync.Mutex; //通道,用于保存资源 res chan Resource; //工厂方法 factory Factory; //判断资源池是否关闭 closed bool;}//创建一个资源池func NewResourcePool(factory Factory, cap int) (*ResourcePool, error) { if cap > 0 { return &ResourcePool{ mu: sync.Mutex{}, res: make(chan Resource, cap), factory: factory, closed: false, }, nil; } return nil, errors.New("cap应大于0");}//从资源池中获取一个资源func (rp *ResourcePool) Get() (Resource, error) { if rp.closed { return nil, errors.New("资源池已关闭"); } select { //获取资源,判断通道是否关闭 case item, ok := <-rp.res: { if !ok { return nil, errors.New("资源池已关闭"); } return item, nil; } default: { //返回工厂创建的资源 return rp.factory(); } }}//将资源放入池中func (rp *ResourcePool) Put(res Resource) error { if rp.closed { return errors.New("资源池已关闭"); } select { //当res无法插入时,这里会阻塞,select执行default case rp.res <- res: { return nil; } default: { res.Close(); return errors.New("资源池已满"); } }}//关闭资源池func (rp *ResourcePool) Close() { if rp.closed { return; } rp.mu.Lock(); //关闭资源池 rp.closed = true; //关闭通道,不在往通道中添加新资源 close(rp.res); //循环关闭通道中的资源 for item := range rp.res { if !item.IsClosed() { item.Close(); } } rp.mu.Unlock();}//自定义一个资源类型type Data struct { data []byte;}func (d Data) Close() { d.data = nil;}func (d Data) IsClosed() bool { if len(d.data) > 0 { return true; } else { return false; }}func (d Data) Write(b []byte) { copy(d.data, b);}func main() { //创建一个资源池 pool, _ := NewResourcePool(func() (Resource, error) { return Data{ data: make([]byte, 16), }, nil; }, 3); //获取资源 item1, _ := pool.Get(); item1.(Data).Write([]byte("123")); item2, _ := pool.Get(); item2.(Data).Write([]byte("456")); item3, _ := pool.Get(); item3.(Data).Write([]byte("789")); fmt.Println(item1); fmt.Println(item2); fmt.Println(item3); //我们再获取一个资源 item4, _ := pool.Get(); //我们把源资入回池中 pool.Put(item1); pool.Put(item2); pool.Put(item3); //这里就会报错了,因为我们创建池时,设置的大小为3 err := pool.Put(item4); if err != nil { fmt.Println(err); } //关闭资源池 pool.Close();}
golang 创建一个简单的资源池,重用资源,减少GC负担
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。