2016-02-10 73 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行以上的消耗,这只会导致在工人完成之前完成调度,它不会加快或减慢任何事情 –