golang 创建一个简单的资源池,重用资源,减少GC负担
2017-07-24 17:35
375 查看
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 创建一个简单的连接池,减少频繁的创建与关闭
- golang 创建一个简单的连接池,减少频繁的创建与关闭
- golang 创建一个简单的广播echo服务器
- 浅谈Golang中创建一个简单的服务器的方法
- Intellijidea2017.03版创建一个简单的Servlet的demo
- Java【多线程知识总结(6)】使用Runnable接口创建多线程,处理同一个资源
- iOS开发】 CoreText 使用教程:以创建一个简单的杂志应用为例
- Core Animation - 第一次使用图层来创建一个简单的项目
- CSS学习之创建一个简单的导航栏下拉菜单
- C调用LUA创建一个简单的LUA解释器
- 创建一个简单的ArcGIS Server ASP.NET网页(转载)
- 使用Angular4+kendo ui for Angular+ webapi+sqlserver创建一个简单的省市选择程序(三)
- Access创建一个简单MIS管理系统
- 《JVM垃圾回收相关内容》开发中,如何尽量减少GC开销,减轻垃圾回收的负担
- Android官方教程翻译(3)——创建一个简单的用户界面
- 使用Spring来创建一个简单的工作流引擎
- [使用心得]maven2之m2eclipse使用手册之六使用Maven2插件创建一个简单的SSH2项目之tomcat篇
- 导入Flex/Flash项目后的一个简单错误:无法创建 HTML 包装器
- H5创建一个简单的自动幻灯片
- CoreText 使用教程:以创建一个简单的杂志应用为例