【转】Go by Example: Worker Pools

原文:https://gobyexample.com/worker-pools

Our running program shows the 5 jobs being executed by various workers. The program only takes about 2 seconds despite doing about 5 seconds of total work because there are 3 workers operating concurrently.

package main

import (
    "fmt"
    "time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Println("worker", id, "started  job", j)
        time.Sleep(time.Second)
        fmt.Println("worker", id, "finished job", j)
        results <- j * 2
    }
}

func main() {

    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

    for a := 1; a <= numJobs; a++ {
        <-results
    }
}

  

下面这个版本为什么会死锁呢??

 package main
 
 import "fmt"
 import "time"
 
 // Here's the worker, of which we'll run several
 // concurrent instances. These workers will receive
 // work on the `jobs` channel and send the corresponding
 // results on `results`. We'll sleep a second per job to
 // simulate an expensive task.
 func worker(id int, jobs <-chan int, results chan<- int) {
     for j := range jobs {
         fmt.Println("worker", id, "started  job", j)
         time.Sleep(time.Second)
         fmt.Println("worker", id, "finished job", j)
         results <- j * 2
     }
 }
 
 func main() {
 
     // In order to use our pool of workers we need to send
     // them work and collect their results. We make 2
     // channels for this.
     jobs := make(chan int, 100)
     results := make(chan int, 100)
 
     // This starts up 3 workers, initially blocked
     // because there are no jobs yet.
     for w := 1; w <= 3; w++ {
         go worker(w, jobs, results)
     }
 
     // Here we send 5 `jobs` and then `close` that
     // channel to indicate that's all the work we have.
     for j := 1; j <= 5; j++ {
         jobs <- j
     }
     close(jobs)
 
     // Finally we collect all the results of the work.
     //for a := 1; a <= 5; a++ {
     //   fmt.Println( <-results)
     //}
     for v := range results {
       fmt.Println(v)
     }
 }

  

——————————————————————————————————————————————————————————

In this example we’ll look at how to implement a worker pool using goroutines and channels.

 
 
package main
 
import (
    "fmt"
    "time"
)

Here’s the worker, of which we’ll run several concurrent instances. These workers will receive work on the jobschannel and send the corresponding results on results. We’ll sleep a second per job to simulate an expensive task.

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Println("worker", id, "started  job", j)
        time.Sleep(time.Second)
        fmt.Println("worker", id, "finished job", j)
        results <- j * 2
    }
}
 
func main() {

In order to use our pool of workers we need to send them work and collect their results. We make 2 channels for this.

    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

This starts up 3 workers, initially blocked because there are no jobs yet.

    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

Here we send 5 jobs and then close that channel to indicate that’s all the work we have.

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

Finally we collect all the results of the work. This also ensures that the worker goroutines have finished. An alternative way to wait for multiple goroutines is to use a WaitGroup.

    for a := 1; a <= numJobs; a++ {
        <-results
    }
}

Our running program shows the 5 jobs being executed by various workers. The program only takes about 2 seconds despite doing about 5 seconds of total work because there are 3 workers operating concurrently.

原文地址:https://www.cnblogs.com/oxspirt/p/13631529.html