• 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();
    }
    

      

  • 相关阅读:
    Gradle学习之基础篇
    springmvc上传文件方法及注意事项
    SpringCloud学习之feign
    SpringCloud学习之eureka集群配置
    SpringMvc+Spring+MyBatis 基于注解整合
    SpringBoot学习之SpringBoot执行器
    SpringBoot跨域问题解决方案
    SpringCloud学习之快速搭建分布式配置
    MySQL-Innodb存储结构
    PG-流复制
  • 原文地址:https://www.cnblogs.com/jkko123/p/7230132.html
Copyright © 2020-2023  润新知