最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Go語言實現(xiàn)一個簡單的無界資源池

 更新時間:2024年05月06日 10:02:07   作者:shark_chili  
本文我們希望通過go語言實現(xiàn)一個簡單的資源池,而這個資源池的資源包括但不限于數(shù)據(jù)庫連接池,線程池,協(xié)程池,網(wǎng)絡(luò)連接池,只要這些資源實現(xiàn)我們指定的關(guān)閉方法,則都可以通過我們封裝的資源池進行統(tǒng)一管理,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下

寫在文章開頭

我們希望通過go語言實現(xiàn)一個簡單的資源池,而這個資源池的資源包括但不限于:

  • 數(shù)據(jù)庫連接池
  • 線程池
  • 協(xié)程池
  • 網(wǎng)絡(luò)連接池

只要這些資源實現(xiàn)我們指定的關(guān)閉方法,則都可以通過我們封裝的資源池進行統(tǒng)一管理,需要簡單說明一下這個資源池的要求:

  • 需要用戶指定資源以及資源的創(chuàng)建方法。
  • 當(dāng)協(xié)程通過Acquire方法獲取資源時,若發(fā)現(xiàn)當(dāng)前池中有資源可以分配則直接返回,若沒有足夠的資源則基于傳入的創(chuàng)建方法創(chuàng)建一個全新的資源分配。
  • 支持資源釋放和資源池關(guān)閉。

聽起來很像是Java的無界線程池,接下來我們就基于這個需求實現(xiàn)一個版本。

需求落地

給出資源池結(jié)構(gòu)

我們首先需要給出資源池的結(jié)構(gòu),很明顯作為一個資源池它需要有一個管理資源池的channel,為了保證多協(xié)程競爭資源的協(xié)程安全,我們還需要通過一把Mutex完成操作互斥,同時給出創(chuàng)建資源的工廠方法要求這個工廠方法創(chuàng)建的資源具備資源關(guān)閉能力:

// Pool 定義一個結(jié)構(gòu)體 包含重量級鎖 有緩沖區(qū)Chanel 工廠方法 連接池關(guān)閉狀態(tài)
type Pool struct {
 m        sync.Mutex
 resource chan io.Closer
 factory  func() (io.Closer, error)
 closed   bool
}

創(chuàng)建資源池

有個上述的定義之后,我們的創(chuàng)建方法就很容易實現(xiàn)了,只需基于外部的size和工廠方法完成Pool成員變量初始化即可:

var ErrPoolClosed = errors.New("連接池已關(guān)閉")


func New(fn func() (io.Closer, error), size uint) (*Pool, error) {
 //判斷size大小是否合法
 if size <= 0 {
  return nil, errors.New("size不合法")
 }
 //基于工廠方法和size創(chuàng)建資源池
 return &Pool{
  resource: make(chan io.Closer, size),
  factory:  fn,
 }, nil

}

獲取資源

當(dāng)協(xié)程需要獲取資源時,會查看當(dāng)前緩沖通道是否有足夠的資源,如果有則在正確運行的情況下返回出去,反之基于我們上文傳入的工廠方法完成資源創(chuàng)建并返回:

func (p *Pool) Acquire() (io.Closer, error) {
 select {
 //如果channel有足夠的資源分配則直接返回
 case r, ok := <-p.resource:
  if !ok {
   log.Println("連接池已關(guān)閉")
   return nil, ErrPoolClosed
  }
  log.Println("拿到連接池共享資源")
  return r, nil
  //基于工廠方法創(chuàng)建全新的資源返回出去
 default:
  log.Println("資源不足,創(chuàng)建新的連接資源")
  return p.factory()
 }

}

釋放與關(guān)閉

這里我們將資源的釋放和關(guān)閉放在一起說明,在進行資源釋放和關(guān)閉時我們需要考慮3個問題即:

  • 已關(guān)閉的資源池?zé)o需歸還資源。
  • 正在關(guān)閉資源池時不可歸還資源。
  • 正在歸還資源時不可關(guān)閉資源池。

所以進行這兩個操作時,我們需要通過互斥鎖確保兩個操作互斥:

// Release 上鎖 設(shè)置方法退出后解鎖 查看當(dāng)前連接池是否已關(guān)閉,若關(guān)閉則直接將資源關(guān)閉 ,反之select查看能否將其存入緩沖區(qū),若可以輸出入隊成功,反之輸出隊列已滿
func (p *Pool) Release(r io.Closer) {
 //上鎖確保關(guān)閉和歸還資源操作互斥
 p.m.Lock()
 //函數(shù)退出時解鎖
 defer p.m.Unlock()
 //如果資源池關(guān)閉則直接將當(dāng)前資源關(guān)閉銷毀
 if p.closed {
  log.Println("連接池已關(guān)閉,直接銷毀當(dāng)前資源")
  r.Close()
 }
 //將連接歸還,如果滿了則直接關(guān)閉銷毀
 select {
 case p.resource <- r:
  log.Println("連接歸還成功")
 default:
  log.Println("連接池已滿,資源直接銷毀")
  r.Close()
 }

}

// Close 方法 上鎖 設(shè)置方法退出后解鎖 遍歷所有資源將其關(guān)閉 然后再關(guān)閉連接池
func (p *Pool) Close() {
 p.m.Lock()

 defer p.m.Unlock()

 if p.closed {
  log.Println("連接池已關(guān)閉,直接銷毀當(dāng)前資源")
  return
 }
 //設(shè)置為關(guān)閉
 p.closed = true
 //關(guān)閉資源
 close(p.resource)
 //遍歷資源池資源
 for r := range p.resource {
  r.Close()
 }

}

測試代碼與輸出

最后我們給出測試代碼,可以看到我們基于資源池工具類模擬數(shù)據(jù)庫連接池的管理:

//設(shè)置最大協(xié)程數(shù)與資源池數(shù)為24
const maxGoroutines = 24
const poolResources = 24

//創(chuàng)建可關(guān)閉的數(shù)據(jù)庫連接
type dbConnection struct {
 ID int32
}
//對應(yīng)的關(guān)閉方法
func (d *dbConnection) Close() error {
 log.Println("當(dāng)前數(shù)據(jù)庫連接", d.ID, "已關(guān)閉")
 return nil
}

var idCounter int32

func createConnection() (io.Closer, error) {
 id := atomic.AddInt32(&idCounter, 1)
 return &dbConnection{ID: id}, nil
}

func main() {
 //創(chuàng)建maxGoroutines個WaitGroup
 var wg sync.WaitGroup
 wg.Add(maxGoroutines)
 //傳入createConnection方法和連接池大小poolResources創(chuàng)建數(shù)據(jù)庫連接池
 p, err := pool.New(createConnection, poolResources)
 if err != nil {
  log.Println(err)
 }
 //創(chuàng)建24個協(xié)程獲取資源
 for i := 0; i < maxGoroutines; i++ {
  go func(queryParam int) {
   queryData(queryParam, p)
   defer wg.Done()
  }(i)
 }
 //等待操作完成關(guān)閉連接池
 wg.Wait()
 log.Println("查詢完成")
 p.Close()

}
//queryData 基于連接池Acquire獲取資源,完成后通過Release歸還資源
func queryData(queryParam int, p *pool.Pool) {

 r, e := p.Acquire()
 if e != nil {
  log.Println(e)
  return
 }

 defer p.Release(r)

 time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
 log.Println("查詢", queryParam, "使用連接", r.(*dbConnection).ID)
}

同時我們給出輸出結(jié)果:

2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 資源不足,創(chuàng)建新的連接資源
2024/05/05 23:36:10 查詢 17 使用連接 14
2024/05/05 23:36:10 連接歸還成功
2024/05/05 23:36:10 查詢 5 使用連接 5
2024/05/05 23:36:10 連接歸還成功
2024/05/05 23:36:10 查詢 3 使用連接 2
2024/05/05 23:36:10 連接歸還成功
2024/05/05 23:36:10 查詢 19 使用連接 19
2024/05/05 23:36:10 連接歸還成功
.......

小結(jié)

到此這篇關(guān)于使用Go實現(xiàn)一個簡單的無界資源池的文章就介紹到這了,更多相關(guān)Go無界資源池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言表達式的求值順序

    Go語言表達式的求值順序

    本文詳細(xì)講解了Go語言中的變量求值順序規(guī)則,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-06-06
  • Golang 經(jīng)典校驗庫 validator 用法解析

    Golang 經(jīng)典校驗庫 validator 用法解析

    這篇文章主要為大家介紹了Golang 經(jīng)典校驗庫 validator 用法解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • GoLang之go build命令的具體使用

    GoLang之go build命令的具體使用

    本文主要介紹了GoLang之go build命令的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 關(guān)于Golang變量初始化/類型推斷/短聲明的問題

    關(guān)于Golang變量初始化/類型推斷/短聲明的問題

    這篇文章主要介紹了關(guān)于Golang變量初始化/類型推斷/短聲明的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • Golang實現(xiàn)拓?fù)渑判?DFS算法版)

    Golang實現(xiàn)拓?fù)渑判?DFS算法版)

    這篇文章主要介紹了Golang實現(xiàn)拓?fù)渑判?DFS算法版),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 如何使用工具自動監(jiān)測SSL證書有效期并發(fā)送提醒郵件

    如何使用工具自動監(jiān)測SSL證書有效期并發(fā)送提醒郵件

    本文介紹了如何開發(fā)一個工具,用于每日檢測SSL證書剩余有效天數(shù)并通過郵件發(fā)送提醒,工具基于命令行,通過SMTP協(xié)議發(fā)送郵件,需配置SMTP連接信息,本文還提供了配置文件樣例及代碼實現(xiàn),幫助用戶輕松部署和使用該工具
    2024-10-10
  • 關(guān)于golang高并發(fā)的實現(xiàn)與注意事項說明

    關(guān)于golang高并發(fā)的實現(xiàn)與注意事項說明

    這篇文章主要介紹了關(guān)于golang高并發(fā)的實現(xiàn)與注意事項說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • GO項目部署Linux服務(wù)器的實現(xiàn)示例

    GO項目部署Linux服務(wù)器的實現(xiàn)示例

    本文主要介紹了GO項目部署Linux服務(wù)器的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • Go語言使用組合的方式實現(xiàn)多繼承的方法

    Go語言使用組合的方式實現(xiàn)多繼承的方法

    這篇文章主要介紹了Go語言使用組合的方式實現(xiàn)多繼承的方法,實例分析了多繼承的原理與使用組合方式來實現(xiàn)多繼承的技巧,需要的朋友可以參考下
    2015-02-02
  • golang通過反射設(shè)置結(jié)構(gòu)體變量的值

    golang通過反射設(shè)置結(jié)構(gòu)體變量的值

    這篇文章主要介紹了golang通過反射設(shè)置結(jié)構(gòu)體變量的值操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評論

上栗县| 务川| 宜章县| 凤冈县| 南部县| 商水县| 涞源县| 岳阳县| 清河县| 南通市| 河南省| 东丽区| 胶州市| 胶南市| 藁城市| 沙坪坝区| 楚雄市| 武城县| 辰溪县| 犍为县| 青田县| 二连浩特市| 长汀县| 清水县| 金秀| 开江县| 武胜县| 石台县| 颍上县| 靖西县| 天门市| 阳新县| 安吉县| 扶余县| 贵德县| 鄱阳县| 七台河市| 永州市| 岱山县| 巴中市| 鲜城|