2016-02-10 71 views
1

所以我用go來討論這個問題很多。假設我有一個包含100,000行文本的文本文件。現在我想將所有這些行保存到數據庫中。所以我會做這樣的事情:限制運行的併發任務數

file, _ := iotuil.ReadFile("file.txt") 

fileLines := strings.Split(string(file), "\n") 

現在我會遍歷文件中的所有行:

for _, l := range fileLines{ 
    saveToDB(l) 
} 

現在我想運行這個saveToDB FUNC同時:

var wg sync.WaitGroup 

for _, l := range fileLines{ 
    wg.Add(1) 
    go saveToDB(l, &wg) 
} 

wg.Wait() 

我不知道這是否有問題,但會運行100,000個併發功能。有沒有什麼辦法說嘿嘿跑100個併發功能等所有這些完成再跑100多呢。

for i, _ := range fileLine { 
    for t = 0; t < 100; t++{ 
    wg.Add(1) 
    go saveToDB(fileLine[i], &wg) 
    } 
    wg.Wait() 
} 

我需要做這樣的事情還是有更清晰的方式去做這件事?還是我運行100,000個併發任務不是問題?

+0

的話題偉大的閱讀:http://nesv.github.io/golang/2014/02 /25/worker-queues-in-go.html – Rodrigo

回答

3

我認爲最好的方法是保持一個工人的例行公事,在渠道中爲他們派遣工作,然後關閉渠道以便他們退出。

是這樣的:

// create a channel for work "tasks" 
ch := make(chan string) 

wg := sync.WaitGroup{} 

// start the workers 
for t = 0; t < 100; t++{ 
    wg.Add(1) 
    go saveToDB(ch, &wg) 
} 

// push the lines to the queue channel for processing 
for _, line := range fileline { 
    ch <- line 
} 

// this will cause the workers to stop and exit their receive loop 
close(ch) 

// make sure they all exit 
wg.Wait() 

然後saveFunction看起來是這樣的:

func saveToDB(ch chan string, wg *sync.WaitGroup) { 
    // cnosume a line 
    for line := range ch { 
     // do work 
     actuallySaveToDB(line) 
    } 
    // we've exited the loop when the dispatcher closed the channel, 
    // so now we can just signal the workGroup we're done 
    wg.Done() 
} 
+0

是的,這是一個很好的使用Go提供的構造。 – evanmcdonnal

+0

我會對上述內容做的一個補充是使其成爲緩衝頻道,因此您不會爲頻道寫入無限制的新行。 https://golang.org/doc/effective_go.html#channels – Sean

+0

@Sean你不會爲頻道寫入無限制的新線路,如果它沒有被緩衝 - 你根本就不會發送線路,除非所有的工作人員都有消耗一切。一個緩衝通道可以讓你寫N行以上的消耗,這隻會導致在工人完成之前完成調度,它不會加快或減慢任何事情 –