Организация структуры Worker Pool в Go является очень полезным и эффективным подходом для обработки асинхронных задач. Worker Pool представляет собой группу рабочих горутин (goroutines), которые выполняют задачи из очереди в фоновом режиме. Это позволяет контролировать количество одновременно выполняющихся задач и избежать перегрузки системы ресурсами.
Для начала необходимо создать структуру, представляющую рабочего. Рабочий должен иметь доступ к входной очереди задач, а также к каналу для коммуникации с главной горутиной. Он также должен уметь выполнять задачи из очереди до тех пор, пока не получит сигнал остановки:
type Worker struct { ID int Tasks chan Task Quit chan bool } func NewWorker(id int) Worker { return Worker{ ID: id, Tasks: make(chan Task), Quit: make(chan bool), } } func (w Worker) Start() { go func() { for { select { case task := <-w.Tasks: // выполнить задачу case <-w.Quit: return } } }() } func (w Worker) Stop() { go func() { w.Quit <- true }() }
Теперь создадим структуру Worker Pool, которая будет содержать группу рабочих, а также входную очередь задач и канал для ожидания завершения работы всех рабочих:
type WorkerPool struct { Workers []Worker Tasks chan Task Completion chan bool } func NewWorkerPool(size int) WorkerPool { pool := WorkerPool{ Workers: make([]Worker, size), Tasks: make(chan Task), Completion: make(chan bool), } for i := 0; i < size; i++ { pool.Workers[i] = NewWorker(i) } return pool } func (pool WorkerPool) Start() { for _, worker := range pool.Workers { worker.Start() } go func() { for { select { case task := <-pool.Tasks: go func(task Task) { worker := <-pool.Workers worker.Tasks <- task pool.Workers <- worker }(task) } } }() } func (pool WorkerPool) Stop() { for _, worker := range pool.Workers { worker.Stop() } for _, worker := range pool.Workers { <-worker.Quit } go func() { pool.Completion <- true }() }
Теперь можно использовать Worker Pool следующим образом:
func main() { pool := NewWorkerPool(5) pool.Start() for i := 0; i < 10; i++ { task := Task{ID: i} pool.Tasks <- task } pool.Stop() <-pool.Completion fmt.Println("Все задачи выполнены") }
В этом примере мы создаем пул из 5 рабочих, запускаем его и отправляем в очередь 10 задач. Затем останавливаем пул и ожидаем, пока все задачи будут выполнены. После этого выводим сообщение о завершении работы.
Таким образом, мы организовали структуру Worker Pool в Go, которая позволяет выполнять асинхронные задачи с ограничением одновременно выполняющихся задач. Это улучшает производительность и эффективность при обработке больших объемов работы.