2016-02-10 4 views
1

Так что я часто сталкиваюсь с этой проблемой с go. Предположим, у меня есть текстовый файл со 100 000 строк текста. Теперь я хочу сохранить все эти строки в db. Так что я хотел бы сделать что-то вроде этого:Ограничение количества выполняемых одновременных задач

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 строк больше, чем они потребляли, что приведет к простому завершению диспетчеризации до того, как рабочие закончат, это не ускорит и не замедлит что-либо –

Смежные вопросы