Этот сайт использует cookies. Продолжение работы с сайтом означает, что Вы согласны!
Ожидание завершения всех потоков
Как уже говорилось, потоки автоматически завершают работу при выходе потока управления из функции main()
, поэтому важно дождаться окончания выполнения потоков. В предыдущих примерах для этого мы использовали функции Sleep()
и Scanln()
. Однако трудно назвать эти способы универсальными. Какое время указать внутри функции Sleep()
, чтобы потоки успели полностью выполниться и при этом пользователю не пришлось ждать, если потоки завершились раньше этого времени? Угадать это значение невозможно. Одним из способов решения проблемы является использование структуры WaitGroup
из пакета sync
.
Структура WaitGroup
содержит следующие методы:
Add()
— добавляет указанное количество потоков к существующему значению счетчика. Значение может быть отрицательным. Если счетчик будет иметь отрицательное значение, то генерируется паника. Формат метода:
(*sync.WaitGroup).Add(delta int)
Done()
— уменьшает значение счетчика на единицу. Этот метод следует вызывать при завершении потока. Формат метода:
(*sync.WaitGroup).Done()
Wait()
— блокирует выполнение потока до тех пор, пока значение счетчика не станет равно нулю. Формат метода:
(*sync.WaitGroup).Wait()
WaitGroup
.Пример использования структуры WaitGroup
приведен в листинге 18.3.
Листинг 18.3. Ожидание завершения всех потоков
package main
import (
"fmt"
"sync"
"time"
)
func main() {
fmt.Println("Начало функции main()")
var wg sync.WaitGroup
for i := 1; i < 4; i++ {
wg.Add(1) // Увеличиваем счетчик потоков на единицу
go func(n int) {
defer wg.Done() // Уменьшаем счетчик потоков на единицу
for j := 1; j < 11; j++ {
fmt.Println("Поток:", n, "j =", j)
time.Sleep(time.Second) // Имитация выполнения задачи
}
}(i)
}
wg.Wait() // Ожидаем завершения всех потоков
fmt.Println("Конец функции main()")
}