golang的channel除了goroutine通信之外還有很多其他的功能圃庭,本文將實(shí)現(xiàn)一種基于channel的通用連接池鹰溜。
何為通用序芦?
連接池的實(shí)現(xiàn)不依賴具體的實(shí)例,而依賴某個(gè)接口,本文的連接池選用的是?io.Closer?接口鲤遥,只要是實(shí)現(xiàn)了該接口的對(duì)象都可以被池管理沐寺。
當(dāng)然,你可以實(shí)現(xiàn)基于?interface{}?的連接池盖奈,這樣任何對(duì)象都可以被管理混坞。
實(shí)現(xiàn)原理
將連接句柄存入channel中,由于緩存channel的特性卜朗,獲取連接時(shí)如果池中有連接拔第,將直接返回咕村,如果池中沒有連接场钉,將阻塞或者新建連接(沒超過最大限制的情況下)。
由于面向接口編程懈涛,所有創(chuàng)建連接的邏輯是不清楚的逛万,這里需要傳入一個(gè)函數(shù),該函數(shù)返回一個(gè)?io.Closer?對(duì)象批钠。
實(shí)現(xiàn)
由于并發(fā)問題宇植,在需要操作池中互斥數(shù)據(jù)的時(shí)候需要加鎖。
package pool
import (
"errors"
"io"
"sync"
"time"
)
var(
ErrInvalidConfig=errors.New("invalid pool config")
ErrPoolClosed=errors.New("pool closed")
)
type factory func()(io.Closer,error)
type Pool interface{
Acquire()(io.Closer,error)//獲取資源
? Release(io.Closer)error? //釋放資源
? Close(io.Closer)error? //關(guān)閉資源
? Shutdown()error? //關(guān)閉池
}
type GenericPool struct{
sync.Mutex
? pool? chan io.Closer
? maxOpen int? //池中最大值
? numOpen? ? int? ? ? //池中資源數(shù)
? minOpen int? ? //池中最小值
? closed bool? ? //池是否關(guān)閉
? maxLifeTime time.Duration
? factory factory //創(chuàng)建連接的方法
}
func NewGenericPool(minOpen,maxOpen int,maxLifetime time.Duration,factory factory)(*GenericPool,error){
if maxOpen<=0||minOpen>maxOpen{
return nil,ErrInvalidConfig
? }
p:=&GenericPool{
pool:make(chan io.Closer,maxOpen),
maxOpen:maxOpen,
minOpen:minOpen,
maxLifeTime:maxLifetime,
factory:factory,
}
for i:=0;i
closer,err:=factory()
if err!=nil{
continue
? ? ? }
p.numOpen++
p.pool<-closer
? }
return p,nil
}
func (p *GenericPool)Acquire()(io.Closer,error){
if p.closed{
return nil,ErrPoolClosed
? }
for? {
closer,err:=p.getOrCreate()
if err!=nil{
return nil,err
? ? ? }
return closer,nil
? }
}
func(p *GenericPool)getOrCreate()(io.Closer,error){
select{
case closer:=<-p.pool:
return closer,nil
? default:
}
p.Lock()
if p.numOpen>=p.maxOpen{
closer:=<-p.pool
? ? ? p.Unlock()
return closer,nil
? }
//新建連接
? closer,err:=p.factory()
if err!=nil{
p.Unlock()
return nil,err
? }
p.numOpen++
p.Unlock()
return closer,nil
}
//釋放單個(gè)資源到連接池
func (p *GenericPool)Release(closer io.Closer)error{
if p.closed? ? {
return ErrPoolClosed
? }
p.Lock()
p.pool<-closer
? p.Unlock()
return nil
}
//關(guān)閉單個(gè)資源
func (p *GenericPool)Close(closer io.Closer)error{
p.Lock()
closer.Close()
p.numOpen--
p.Unlock()
return nil
}
//關(guān)閉連接池埋心,釋放所有資源
func(p *GenericPool)ShutDown()error{
if p.closed{
return? ErrPoolClosed
? }
p.Lock()
close(p.pool)
for closer:=range p.pool{
closer.Close()
p.numOpen--
}
p.closed=true
? p.Unlock()
return nil
}
基于該連接池指郁,可以管理所有?io.Closer?對(duì)象。比如?memcached?,?redis?等等拷呆,非常方便闲坎!
————————————————
版權(quán)聲明:本文為CSDN博主「貓哭」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議茬斧,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明腰懂。
原文鏈接:https://blog.csdn.net/mengxinghuiku/java/article/details/79730871