zoukankan      html  css  js  c++  java
  • 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();
    }
    

      

  • 相关阅读:
    POJ 3710 Christmas Game#经典图SG博弈
    POJ 2599 A funny game#树形SG(DFS实现)
    POJ 2425 A Chess Game#树形SG
    LeetCode Array Easy 122. Best Time to Buy and Sell Stock II
    LeetCode Array Easy121. Best Time to Buy and Sell Stock
    LeetCode Array Easy 119. Pascal's Triangle II
    LeetCode Array Easy 118. Pascal's Triangle
    LeetCode Array Easy 88. Merge Sorted Array
    ASP.NET MVC 学习笔记之 MVC + EF中的EO DTO ViewModel
    ASP.NET MVC 学习笔记之面向切面编程与过滤器
  • 原文地址:https://www.cnblogs.com/jkko123/p/7230132.html
Copyright © 2011-2022 走看看