2017-12-28 12 views
1

나는 Golang의 for 루프를 사용하여 동시에 1000 개의 goroutines를 시작한다고 생각합니다.
문제는 다음과 같습니다. 모든 goroutine이 실행되었는지 확인해야합니다.
채널을 사용하여이를 확인하는 것이 가능합니까?Golang에서 채널로 많은 goroutines를 처리하는 방법

구조는 다음과 같이 좀 있습니다 :

func main { 
    for i ... { 
     go ... 
     ch? 
    ch? 
} 
+2

goroutines가 끝날 때까지 기다리시겠습니까? 그렇다면'sync.WaitGroup'을 사용할 수 있습니다. https://golang.org/pkg/sync/#WaitGroup을 참조하십시오. –

+0

나는이 일을 이해하지 못할 수도있다. 당신은 1000 * 다른 * goroutines을 가지고 있습니까? 그렇지 않은 경우 - 동일한 작업을 수행하면 어떤 항목이 제외 되었습니까? –

답변

0

예, this을 시도 :

package main 

import (
    "fmt" 
) 

const max = 1000 

func main() { 
    for i := 1; i <= max; i++ { 
     go f(i) 
    } 

    s := 0 
    for i := 1; i <= max; i++ { 
     s += <-ch 
    } 

    fmt.Println(s) 
} 

func f(n int) { 
    // do a job here 
    ch <- n 
} 

var ch = make(chan int, max) 

출력 :

500500 
+0

이것이 작동하고 OP의 제약 조건을 충족시키는 경우에도 이것이 최선의 방법은 아닙니다. 이 ad-hoc 방식의 문제점은 유지 보수성과 확장 성입니다. 'WaitGroup'은이 문제를 해결하기 위해 고안되었습니다. –

+0

@KshitijSaraogi : 모범 사례는 바로 가까운 문제에 달려 있습니다. 예 : 1000 개의 goroutines가 특정 계산을 수행하고 'int'결과를 메인 goroutine으로 보내는 것이 필요하다고 가정하면 이것이 최선의 방법입니다. –

2

@Andy 당신이 이것을 달성하기 위해 sync.WaitGroup을 사용할 수 있습니다 언급 한 바와 같이. 아래는 그 예입니다. 희망찬 코드는 자명하다.

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func dosomething(millisecs int64, wg *sync.WaitGroup) { 
    defer wg.Done() 
    duration := time.Duration(millisecs) * time.Millisecond 
    time.Sleep(duration) 
    fmt.Println("Function in background, duration:", duration) 
} 

func main() { 
    arr := []int64{200, 400, 150, 600} 
    var wg sync.WaitGroup 
    for _, n := range arr { 
    wg.Add(1) 
    go dosomething(n, &wg) 
    } 
    wg.Wait() 
    fmt.Println("Done") 
} 
+1

아마도'dosomething()'의 시작 부분에'woo.Done()'을 연기하면 더 관용적 일 것입니다. – biosckon

0

난 당신이 패턴을 따를 것을 제안합니다. 동시성과 채널은 좋지만 나쁜 방식으로 사용하면 프로그램이 예상보다 느려질 수 있습니다. 다중 작업 루틴 및 채널을 처리하는 간단한 방법은 작업자 풀 패턴을 사용하는 것입니다.

이 간단한 예 here에서 가져

// In this example we'll look at how to implement 
// a _worker pool_ using goroutines and channels. 

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++ { 
     <-results 
    } 
} 

아래의 코드를 자세히 살펴 보자. 또한 results 채널은 실패 통지를 포함하여 작업을 실행하는 모든 이동 루틴을 추적하는 데 도움을 줄 수 있습니다.