新聞中心
能看到這篇文章一定是特殊的緣分,請務必珍惜,請詳細看看吧,哈哈。

目前創(chuàng)新互聯(lián)公司已為1000多家的企業(yè)提供了網(wǎng)站建設、域名、雅安服務器托管、成都網(wǎng)站托管、企業(yè)網(wǎng)站設計、通海網(wǎng)站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
圖片
不止上圖,最近 Go就業(yè)訓練營 中不少小伙伴說,面試中碰到了好幾次讓手撕協(xié)程池的公司。
解題思路:
- 定義協(xié)程池結構體:首先,我們需要定義一個協(xié)程池的結構體,包含協(xié)程池的屬性和方法。結構體中需要包含一個任務隊列、協(xié)程池的大小、當前運行的協(xié)程數(shù)量等屬性。
- 初始化協(xié)程池:在初始化函數(shù)中,我們需要創(chuàng)建一個指定大小的任務隊列,并初始化協(xié)程池的屬性。
- 添加任務到協(xié)程池:當有任務需要執(zhí)行時,我們將任務添加到任務隊列中。
- 啟動協(xié)程池:在啟動函數(shù)中,我們需要根據(jù)協(xié)程池的大小創(chuàng)建對應數(shù)量的協(xié)程,并從任務隊列中獲取任務進行執(zhí)行。每個協(xié)程會不斷從任務隊列中獲取任務并執(zhí)行,直到任務隊列為空。
- 控制協(xié)程數(shù)量:在協(xié)程池中,我們需要控制同時運行的協(xié)程數(shù)量,以防止過多的協(xié)程導致資源浪費??梢允褂眯盘柫炕蛘哂嫈?shù)器來控制協(xié)程的數(shù)量。
通過以上的解題思路,我們可以實現(xiàn)一個基本的協(xié)程池。
在實際應用中,可能還需要考慮一些其他的因素,如任務優(yōu)先級、任務超時處理等。根據(jù)具體的需求,可以對協(xié)程池進行進一步的擴展和優(yōu)化。
說完了解題思路,再給大家一個可參考,可運行的示例代碼:
示例代碼:
package main
import (
"fmt"
"sync"
)
type Job struct {
ID int
}
type Worker struct {
ID int
JobChannel chan Job
Quit chan bool
}
type Pool struct {
WorkerNum int
JobChannel chan Job
WorkerQueue chan chan Job
Quit chan bool
wg sync.WaitGroup
}
// NewWorker 創(chuàng)建一個新的工作者
func NewWorker(id int, workerQueue chan chan Job) Worker {
return Worker{
ID: id,
JobChannel: make(chan Job),
Quit: make(chan bool),
}
}
// Start 啟動工作者
func (w Worker) Start(workerQueue chan chan Job) {
go func() {
for {
workerQueue <- w.JobChannel
select {
case job := <-w.JobChannel:
fmt.Printf("Worker %d started job %d\n", w.ID, job.ID)
// 執(zhí)行任務
fmt.Printf("Worker %d finished job %d\n", w.ID, job.ID)
case <-w.Quit:
return
}
}
}()
}
// Start 啟動工作者池
func (p *Pool) Start() {
for i := 0; i < p.WorkerNum; i++ {
worker := NewWorker(i, p.WorkerQueue)
worker.Start(p.WorkerQueue)
}
go func() {
for {
select {
case job := <-p.JobChannel:
worker := <-p.WorkerQueue
worker <- job
case <-p.Quit:
for i := 0; i < p.WorkerNum; i++ {
worker := <-p.WorkerQueue
worker <- Job{} // 發(fā)送空任務,通知協(xié)程退出
}
p.wg.Done()
return
}
}
}()
}
// AddJob 添加作業(yè)到作業(yè)通道
func (p *Pool) AddJob(job Job) {
p.JobChannel <- job
}
// Stop 停止工作者池
func (p *Pool) Stop() {
p.Quit <- true
p.wg.Wait()
}
func main() {
pool := Pool{
WorkerNum: 5,
JobChannel: make(chan Job),
WorkerQueue: make(chan chan Job, 5),
Quit: make(chan bool),
}
pool.Start()
for i := 0; i < 10; i++ {
job := Job{ID: i}
pool.AddJob(job)
}
pool.Stop()
}以下是對代碼的注釋:
- Job 結構體定義了作業(yè)的 ID。
- Worker 結構體定義了工作者的 ID、作業(yè)通道和退出通道。
- Pool 結構體定義了工作者數(shù)量、作業(yè)通道、工作者隊列和退出通道,以及一個等待組(WaitGroup)。
- NewWorker 函數(shù)創(chuàng)建一個新的工作者,并返回一個工作者實例。
- Start 方法啟動一個工作者,它從工作者隊列中獲取自己的作業(yè)通道,并在循環(huán)中等待作業(yè)的到來,執(zhí)行作業(yè)并在退出通道接收到信號時返回。
- Pool 的 Start 方法啟動工作者池,創(chuàng)建指定數(shù)量的工作者,并將它們啟動。同時,它還啟動一個循環(huán),等待作業(yè)的到來,并將作業(yè)分發(fā)給可用的工作者。
- AddJob 方法將作業(yè)添加到作業(yè)通道中,供工作者池處理。
- Stop 方法停止工作者池,向退出通道發(fā)送信號,并等待所有工作者完成當前作業(yè)后返回。
- main 函數(shù)創(chuàng)建一個工作者池實例,啟動工作者池,并添加一些作業(yè)。最后,調用 Stop 方法停止工作者池。
答疑
有小伙伴提出了疑問:
WorkerQueue chan chan Job 的作用是什么?為什么要這么定義?
解答一下:
WorkerQueue chan chan Job 的作用是用于傳遞工作者(Worker)的作業(yè)通道(JobChannel)。它是一個通道(channel),其中每個元素都是一個作業(yè)通道。
為什么要這么定義呢?這是因為在工作者池模式中,每個工作者需要一個獨立的作業(yè)通道來接收作業(yè)。通過將每個工作者的作業(yè)通道放入一個通道中,可以實現(xiàn)對工作者的動態(tài)分配和管理。
具體來說,WorkerQueue 通道用于存儲每個工作者的作業(yè)通道。當有新的作業(yè)到達時,工作者池會從 WorkerQueue 中取出一個可用的工作者的作業(yè)通道,并將作業(yè)發(fā)送到該通道中,由相應的工作者進行處理。
這種設計可以有效地控制并發(fā)任務的分配和調度。通過將工作者的作業(yè)通道放入 WorkerQueue 中,可以實現(xiàn)對工作者的復用和動態(tài)管理,避免了頻繁地創(chuàng)建和銷毀工作者協(xié)程的開銷。
總結起來,WorkerQueue 的定義允許工作者池動態(tài)地管理工作者的作業(yè)通道,實現(xiàn)對并發(fā)任務的高效分配和調度。
運行結果
圖片
總結
以上代碼實現(xiàn)了一個簡單的工作池(Worker Pool)模式。工作池由一組固定數(shù)量的工作者(Worker)協(xié)程組成,它們從作業(yè)通道(JobChannel)中獲取作業(yè)(Job)并執(zhí)行。
本文轉載自微信公眾號「 程序員升級打怪之旅」,作者「 王中陽Go」,可以通過以下二維碼關注。
轉載本文請聯(lián)系「 程序員升級打怪之旅」公眾號。
分享名稱:不少人面試都掛在這道題了!你掛了嗎?
本文鏈接:http://m.fisionsoft.com.cn/article/djjjipp.html


咨詢
建站咨詢
