golang的channel除了goroutine通信之外還有很多其他的功能,本文將實現(xiàn)一種基于channel的通用連接池。
何為通用?
連接池的實現(xiàn)不依賴具體的實例,而依賴某個接口,本文的連接池選用的是?io.Closer?接口,只要是實現(xiàn)了該接口的對象都可以被池管理。
當(dāng)然,你可以實現(xiàn)基于?interface{}?的連接池,這樣任何對象都可以被管理。
實現(xiàn)原理
將連接句柄存入channel中,由于緩存channel的特性,獲取連接時如果池中有連接,將直接返回,如果池中沒有連接,將阻塞或者新建連接(沒超過最大限制的情況下)。
由于面向接口編程,所有創(chuàng)建連接的邏輯是不清楚的,這里需要傳入一個函數(shù),該函數(shù)返回一個?io.Closer?對象。
實現(xiàn)
由于并發(fā)問題,在需要操作池中互斥數(shù)據(jù)的時候需要加鎖。
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
}
//釋放單個資源到連接池
func (p *GenericPool)Release(closer io.Closer)error{
if p.closed? ? {
return ErrPoolClosed
? }
p.Lock()
p.pool<-closer
? p.Unlock()
return nil
}
//關(guān)閉單個資源
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?對象。比如?memcached?,?redis?等等,非常方便!
————————————————
版權(quán)聲明:本文為CSDN博主「貓哭」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/mengxinghuiku/java/article/details/79730871