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负担全部内容,希望文章能够帮你解决golang 创建一个简单的资源池,重用资源,减少GC负担所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)