Go by Example: [34] Worker Pools

Worker Pools

다음의 예제는, channelgoroutine을 이용해서 Worker Pool을 구현하는 예제 입니다.

package main

import "time"
import "fmt"

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

func main() {
    
    jobs := make(chan int, 100)                                // [2]
    results := make(chan int, 100)
    
    for w := 1; w <= 3; w++ {                                  // [3]
        go worker(w, jobs, results)
    }
    
    for j := 1; j <= 9; j++ {                                  // [4]
        jobs <-j
    }
    close(jobs)
    
    for a := 1; a <= 9; a++ {                                  // [5]
        <-results
    }
}
  1. 작업함수를 선언합니다. 동시에 여러개의 함수를 실행할 것입니다. 이 작업함수는 jobs채널에서
    작업하며, results채널에 작업결과를 전송하게 됩니다. 두번째 작업을 위해서 일정시간 대기합니다.
  2. 현재의 작업풀(worker pool)에서는 작업의 수행하고 해당 수행 결과를 수집하는 것이 목적입니다.
    이렇듯, 특정작업을 수행하는 것과 결과를 수집하는 2개의 채널을 생성하고 사용합니다.
  3. 총 3개의 작업자함수를 시작하고, 현재 수행된 작업이 없으므로, 블럭상태에 둡니다.
  4. 9개의 작업을 처리한후 해당 채널을 종료하고 있습니다.
  5. 마지막으로 수집된 결과를 결과채널에(results) 전송합니다.

실행하면 다음과 같습니다.

$ time go run worker-pools.go 
worker 1 processing job 1
worker 2 processing job 2
worker 3 processing job 3
worker 1 processing job 4
worker 2 processing job 5
worker 3 processing job 6
worker 1 processing job 7
worker 2 processing job 8
worker 3 processing job 9

real	0m3.149s

총 9개의 작업을 수행한 후 처리를 완료하는데 총 3초 가량 소요되었습니다. 이론적으로는 9초가
소요되어야 하나, 동시병렬 실행으로 작동했기때문에 3개 작업을 3번 걸쳐서 해서 3초가 소요되었습니다.