欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

寫在文章開頭

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

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

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

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

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

需求落地

給出資源池結構

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

// Pool 定義一個結構體 包含重量級鎖 有緩沖區(qū)Chanel 工廠方法 連接池關閉狀態(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("連接池已關閉")


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

}

獲取資源

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

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

}

釋放與關閉

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

  • 已關閉的資源池無需歸還資源。
  • 正在關閉資源池時不可歸還資源。
  • 正在歸還資源時不可關閉資源池。

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

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

}

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

 defer p.m.Unlock()

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

}

測試代碼與輸出

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

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

//創(chuàng)建可關閉的數(shù)據(jù)庫連接
type dbConnection struct {
 ID int32
}
//對應的關閉方法
func (d *dbConnection) Close() error {
 log.Println("當前數(shù)據(jù)庫連接", d.ID, "已關閉")
 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)
 }
 //等待操作完成關閉連接池
 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)
}

同時我們給出輸出結果:

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 連接歸還成功
.......

小結

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

相關文章

  • Golang中for循環(huán)的用法示例詳解

    Golang中for循環(huán)的用法示例詳解

    for循環(huán)就是讓一段代碼循環(huán)的執(zhí)行,接下來通過本文給大家講解Golang中for循環(huán)的用法,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • Golang標準庫binary詳解

    Golang標準庫binary詳解

    這篇文章主要介紹了Golang標準庫binary的相關資料,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • Golang接口的定義與空接口及斷言的使用示例

    Golang接口的定義與空接口及斷言的使用示例

    在?Golang?中,接口是一種類型,它是由一組方法簽名組成的抽象集合。這篇文章主要為大家介紹了Golang接口的具體使用,希望對大家有所幫助,空接口是特殊形式的接口類型,普通的接口都有方法,而空接口沒有定義任何方法口,也因此,我們可以說所有類型都至少實現(xiàn)了空接口
    2023-04-04
  • golang執(zhí)行命令獲取執(zhí)行結果狀態(tài)(推薦)

    golang執(zhí)行命令獲取執(zhí)行結果狀態(tài)(推薦)

    這篇文章主要介紹了golang執(zhí)行命令獲取執(zhí)行結果狀態(tài)的相關知識,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2019-11-11
  • Golang標準庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例

    Golang標準庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例

    這篇文章主要為大家介紹了Golang標準庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • 一文弄懂用Go實現(xiàn)MCP服務的示例代碼

    一文弄懂用Go實現(xiàn)MCP服務的示例代碼

    本文主要介紹了一文弄懂用Go實現(xiàn)MCP服務的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-04-04
  • Go語言中重構的技巧分享

    Go語言中重構的技巧分享

    這篇文章主要來和大家分享一下Go語言中重構的技巧,即如何盡量避免使用 else、break 和 continue,從而讓代碼更透明、更易讀,感興趣的小伙伴可以學習一下
    2023-10-10
  • go中的unsafe包及使用詳解

    go中的unsafe包及使用詳解

    Unsafe code是一種繞過go類型安全和內(nèi)存安全檢查的Go代碼。這篇文章主要介紹了go中的unsafe包,需要的朋友可以參考下
    2019-07-07
  • Golang實現(xiàn)斷點續(xù)傳功能

    Golang實現(xiàn)斷點續(xù)傳功能

    這篇文章主要為大家詳細介紹了Golang實現(xiàn)斷點續(xù)傳、復制文件功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Golang中如何使用lua進行擴展詳解

    Golang中如何使用lua進行擴展詳解

    這篇文章主要給大家介紹了關于Golang中如何使用lua進行擴展的相關資料,這是最近在工作中遇到的一個問題,覺著有必要分享出來給大家學習,文中給出了詳細的示例,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-10-10

最新評論