package main import ( "fmt" "sync" ) type Job interface { Do() } type Worker struct { id int jobChannel chan Job done chan bool } type Pool struct { workers []*Worker jobQueue chan Job wg sync.WaitGroup } func NewWorker(id int, wg *sync.WaitGroup) *Worker { worker := Worker{ id: id, jobChannel: make(chan Job), done: make(chan bool), } go func() { for job := range worker.jobChannel { job.Do() } wg.Done() }() return &worker } func NewPool(numWorkers int) *Pool { pool := Pool{ workers: make([]*Worker, numWorkers), jobQueue: make(chan Job), } for i := 0; i < numWorkers; i++ { pool.workers[i] = NewWorker(i, &pool.wg) } go pool.run() return &pool } func (w *Worker) Start(job Job) { w.jobChannel <- job } func (w *Worker) Stop() { close(w.jobChannel) <-w.done } func (p *Pool) run() { for job := range p.jobQueue { worker := p.getAvailableWorker() worker.Start(job) } for _, worker := range p.workers { worker.Stop() } p.wg.Done() } func (p *Pool) getAvailableWorker() *Worker { for { for _, worker := range p.workers { select { case <-worker.done: default: return worker } } } } func (p *Pool) Submit(job Job) { p.wg.Add(1) p.jobQueue <- job } func (p *Pool) Shutdown() { close(p.jobQueue) p.wg.Wait() } type PrintJob struct { id int } func (pj PrintJob) Do() { fmt.Printf("Printing job %d\n", pj.id) } func main() { pool := NewPool(5) for i := 0; i < 10; i++ { pool.Submit(PrintJob{id: i}) } pool.Shutdown() } 
