Go實現設計模式系列(8) Go實現物件池模式

2021-10-08 23:33:08 字數 2799 閱讀 4741

物件池模式,物件被預先建立並初始化後放入物件池中,物件提供者,物件提供者就能利用已有的物件來處理請求,減少物件頻繁建立所浪費的資源。例如資料庫的連線池等等,基本都是建立後就被放入連線池中,後續的查詢請求使用的都是連線池中的物件,從而加快了查詢速度(不然每次查詢都需要重新建立資料庫連線物件,比較浪費)。

一句話解釋,物件池模式下,程式在一開始就建立好了一批可用物件供使用

這種模式下,一般有兩種角色,即物件池管理者和物件池使用者。

物件池管理者負責管理整個物件池,包括初始化物件池,擴充物件池的大小,重置歸還物件的狀態等等。

物件池使用者負責從物件池中獲取乙個物件,用完之後一般需要歸還整這個物件。

一般被放入物件池中的物件包括socket物件,資料庫連線物件(連線池),執行緒物件(執行緒池)等等。

來看看物件池模式的五大要素:

go語言內部有sync.pool包實現了物件池的概念,但是這個設計出來的目的是優化gc的,因為它儲存的物件隨時都有可能被gc**掉,具體感興趣地可以去了解一下該包的用法,這篇文章就不對該包作詳細解答了,因為我們的主要目的還是了解物件池模式。因此下面我們會自己實現乙個物件池。

當前的場景是我們需要實現乙個協程池,我們開始給這個協程池固定乙個協程數量,每個協程被用於去執行一項任務(task),假設當前有1萬個任務,我們必不可能用只用乙個協程去執行,我們開啟若干個協程去不斷地輪詢執行這些任務

object_pool.go:

package objectpool

import

("fmt"

"sync"

)// 任務物件,任務具體做什麼由f決定

type task struct

// 建立乙個任務物件

func

newtask

(f func()

error

,id int

)*task

}// 執行該任務物件

func

(t *task)

execute()

error

// 協程池物件

type pool struct

// 建立乙個協程池

func

newpool

(cap

int, wg *sync.waitgroup)

*pool

}func

(p *pool)

settask

(task *task)

func

(p *pool)

worker

(workid int

)else

// 完成乙個任務done

p.wg.

done()

}}func

(p *pool)

run(

)for task :=

range p.entrychannel

}func

(p *pool)

stop()

object_pool_test.go:

package objectpool

import

("fmt"

"sync"

"testing"

"time"

)func

testobjectpool

(t *testing.t)()

wg :=

&sync.waitgroup

p :=

newpool(10

,wg)

go p.

run(

)// 建立100個task

for i :=

0; i <

100; i++

,i) p.

settask

(t)}

wg.wait()

p.stop()

}

執行測試結果:

==

= run testobjectpool

workerid: 8, the task id 8 was successfully executed

workerid: 2, the task id 4 was successfully executed

....

....

....

.....

....

....

.....

workerid: 6, the task id 2 was successfully executed

workerid: 6, the task id 97 was successfully executed

workerid: 2, the task id 99 was successfully executed

it takes 10.030659 seconds

--- pass: testobjectpool (10.03s)

pass

上述例子在做測試的時候,我特意在每個task任務中 sleep了1秒,保證它們至少執行1秒再推出。如果每個任務中只是列印乙個日誌,這樣我們在測試的時候會發現,可能協程池開的worker數越少越好,因為這個時候在一開始建立多個worker的開銷已經遠遠超過每個任務執行的開銷了。

因此協程數不是開的越多越好,具體開多少個是需要在指定場景進行效能測試才能決定的

Go實現設計模式系列(2) Go實現New模式

這幾乎是我們最常用的模式,因為太常用了,以致於我們並沒有它當成一種模式。new 模式屬於建立型模式的一種,作為最基礎的建立型模式而被我們廣泛使用 來看看new模式的五大要素 我們想要獲取乙個伺服器物件,該伺服器物件實現了start,stop兩個介面 new.go package newimport ...

8 Go語言 指標型別

1.實際用法package main import fmt func main 執行結果 0xc042052088 0xc0420461b02.從指標獲取指標指向的值 在對普通變數使用 操作符取位址獲得這個變數的指標後,可以對指標使用 操作,也就是指標取值 package main import f...

GO學習 8 Go語言基礎之陣列

陣列是同一種資料型別元素的集合。在go語言中,陣列從宣告時就確定,使用時可以修改陣列成員,但是陣列大小不可變化。基本語法 定義乙個長度為3元素型別為int的陣列a var a 3 intvar 陣列變數名 元素數量 t比如 var a 5 int,陣列的長度必須是常量,並且長度是陣列型別的一部分。一...