使用golang編寫(xiě)一個(gè)并發(fā)工作隊(duì)列
其實(shí)golang用一個(gè)函數(shù)可以構(gòu)建一個(gè)并發(fā)隊(duì)列,現(xiàn)在編寫(xiě)一個(gè)靈活可控的隊(duì)列程序
先定義一個(gè)工作
type Worker struct {
ID int
RepJobs chan int64
SM *SM
quit chan bool
}
包含了workid和執(zhí)行任務(wù)的id,上面的SM只是任務(wù)具體內(nèi)容,這個(gè)和具體業(yè)務(wù)相關(guān),大家自己編寫(xiě)自己的SM業(yè)務(wù)邏輯
然后定義工作池
type workerPool struct {
workerChan chan *Worker
workerList []*Worker
}
這個(gè)里面定義了一個(gè)工作隊(duì)列的切片,可以自定義工作隊(duì)列的個(gè)數(shù),甚至后期還可以添加work,還定義了一個(gè)隊(duì)列類(lèi)型的管道。
定義完成過(guò)后就可以初始化工作池了
func InitWorkerPool() error {
n := 3
WorkerPool = &workerPool{
workerChan: make(chan *Worker, n),
workerList: make([]*Worker, 0, n),
}
for i := 0; i < n; i++ {
worker := NewWorker(i)
WorkerPool.workerList = append(WorkerPool.workerList, worker)
worker.Start()
log.Debugf("worker %d started", worker.ID)
}
return nil
}
這個(gè)里面我寫(xiě)死了worker的個(gè)數(shù)是3,當(dāng)然這個(gè)可以通過(guò)讀取配置文件或者參數(shù)傳遞的方式;這個(gè)里面逐一啟動(dòng)work
worker.Start(),這個(gè)是關(guān)鍵
func (w *Worker) Start() {
go func() {
for {
WorkerPool.workerChan <- w
select {
case jobID := <-w.RepJobs:
log.Debugf("worker: %d, will handle job: %d", w.ID, jobID)
w.handleRepJob(jobID)
case q := <-w.quit:
if q {
log.Debugf("worker: %d, will stop.", w.ID)
return
}
}
}
}()
}
這個(gè)就是go 啟動(dòng)一個(gè)協(xié)程,先把自己放到workerChan中,然后不斷從w.RepJobs管道中獲取任務(wù)并執(zhí)行,如果執(zhí)行完成后又把自己放回到隊(duì)列中。
所以如果你要有任務(wù)需要執(zhí)行,放到這個(gè)管道中即可
func Dispatch() {
for {
select {
case job := <-jobQueue:
go func(jobID int64) {
println("Trying to dispatch job: %d", jobID)
worker := <-WorkerPool.workerChan
worker.RepJobs <- jobID
}(job)
}
}
}
從管道中拿出一個(gè)worker并把任務(wù)id放到worker中去執(zhí)行。
當(dāng)然你可以停止worker,甚至可以停止job
func (w *Worker) Stop() {
go func() {
w.quit <- true
}()
}
func (wp *workerPool) StopJobs(jobs []int64) {
log.Debugf("Works working on jobs: %v will be stopped", jobs)
for _, id := range jobs {
for _, w := range wp.workerList {
if w.SM.JobID == id {
log.Debugf("found a worker whose job ID is %d, will try to stop it", id)
w.SM.Stop(id)
}
}
}
}
補(bǔ)充一下,int64和字符串轉(zhuǎn)換。
string到int
int,err:=strconv.Atoi(string)
string到int64
int64, err := strconv.ParseInt(string, 10, 64)
int到string
string:=strconv.Itoa(int)
int64到string
string:=strconv.FormatInt(int64,10)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
- goFrame的隊(duì)列g(shù)queue對(duì)比channel使用詳解
- 關(guān)于golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接的問(wèn)題
- Golang中優(yōu)秀的消息隊(duì)列NSQ基礎(chǔ)安裝及使用詳解
- 基于golang的簡(jiǎn)單分布式延時(shí)隊(duì)列服務(wù)的實(shí)現(xiàn)
- golang實(shí)現(xiàn)redis的延時(shí)消息隊(duì)列功能示例
- Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)圖文示例
相關(guān)文章
Go語(yǔ)言web框架Gin響應(yīng)客戶端的方式
Gin是一個(gè)用Go語(yǔ)言編寫(xiě)的web框架,它是一個(gè)類(lèi)似于martini但擁有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍,本文給大家介紹了Go語(yǔ)言web框架Gin響應(yīng)客戶端有哪些方式,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-10-10
Go語(yǔ)言入門(mén)之基礎(chǔ)語(yǔ)法和常用特性解析
這篇文章主要給大家講解了Go語(yǔ)言的基礎(chǔ)語(yǔ)法和常用特性解析,比較適合入門(mén)小白,文中通過(guò)代碼示例介紹的非常詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的朋友可以參考下2023-07-07
go 語(yǔ)言字符類(lèi)型 byte 與 rune案例詳解
這篇文章主要介紹了go 語(yǔ)言字符類(lèi)型 byte 與 rune案例詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
深入理解Golang?make和new的區(qū)別及實(shí)現(xiàn)原理
在Go語(yǔ)言中,有兩個(gè)比較雷同的內(nèi)置函數(shù),分別是new和make方法,二者都可以用來(lái)分配內(nèi)存,那他們有什么區(qū)別呢?下面我們就從底層來(lái)分析一下二者的不同。感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助2022-10-10
基于gin的golang web開(kāi)發(fā):路由示例詳解
這篇文章主要介紹了基于gin的golang web開(kāi)發(fā):路由示例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
Golang對(duì)struct字段重新排序優(yōu)化數(shù)據(jù)結(jié)構(gòu)性能實(shí)踐
這篇文章主要為大家介紹了Golang對(duì)struct字段重新排序優(yōu)化數(shù)據(jù)結(jié)構(gòu)性能實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
解決golang時(shí)間字符串轉(zhuǎn)time.Time的坑
這篇文章主要介紹了解決golang時(shí)間字符串轉(zhuǎn)time.Time的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
golang簡(jiǎn)易實(shí)現(xiàn)?k8s?的yaml上傳并應(yīng)用示例方案
這篇文章主要為大家介紹了golang簡(jiǎn)易實(shí)現(xiàn)?k8s?的yaml上傳并應(yīng)用示例方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07

