一、協程基本使用
1、啟動一個協程
- 主線程中每個100毫秒打印一次,總共打印2次
- 另外開啟一個協程,打印10次
- 情況一:打印是交替,證明是并行的
- 情況二:開啟的協程打印2次,就退出了(因為主線程退出了)
package mainimport ("fmt""time"
)func test() {for i :=o;i<10;i++ {fmt.PrintIn("test() 你好golang")time.Sleep(time.Millisecond * 100)}
}func main() {go test() //表示開啟一個協程for i:=0;i<2;i++ {fmt.PrintIn("main() 你好golang")time.Sleep(time.Millisecond * 100)}
}
/*
main() 你好golang
test() 你好golang
main() 你好golang
test() 你好golang
test() 你好golang
*/
?2、WaitGroup等待協程執行完畢
- 主線程退出后所有的協程無論有沒有執行完畢都會退出
- 所以我們在主進程中可以通過WaitGroup等待協程執行完畢
- sync.WaitGroup內部維護者一個計數器,計數器的值可以增加和減少
- 例如當我們啟動了N個并發任務時,就將計數器值增加N
- 每個任務完成時通過調用Done()方法將計數器減1
- 通過調用Wait來等待并發任務執行完,當計數器值為0時,表示所有并發任務已經完成
var wg sync.waitGroup? ? ? //第一步:定義一個計數器
wg.Add(1)? ? ? ? ? ? ? ? ? ? ? ? //第二步:開啟一個協程計數器+1
wg.Done()? ? ? ? ? ? ? ? ? ? ? ? //第三步:協程執行完畢,計數器-1
wg.Wait()? ? ? ? ? ? ? ? ? ? ? ? //第四步:計數器為0時退出
package mainimport ("fmt""sync""time"
)var wg sync.WaitGroup //第一步:定義一個計數器func test1() {for i :=0;i<10;i++ {fmt.PrintIn("test1() 你好golang",i)time.Sleep(time.Millisecond * 100)}wg.Done() //協程計數器-1 //第三步:協程執行玩不,計數器-1
}func test2() {for i :=0;i<2;i++ {fmt.PrintIn("test2() 你好golang",i)time.Sleep(time.Millisecond * 100)}wg.Done() //協程計數器-1
}func main() {wg.Add(1) //協程計數器+1 第二不:開啟一個協程計數器+1go test1() //表示開啟一個協程wg.Add(1) //協程計數器+1go test2() //表示開啟一個協程wg.Wait() //等待協程執行完畢... 第四步:計數器為0時退出fmt.PrintIn("主線程退出...")}/*
test2() 你好golang- 0
test1() 你好golang- 0
.....
test1() 你好golang- 8
test1() 你好golang- 9
主線程退出...
*/
?二、多協程案例
1、開啟多個協程
- 在Go語言中實現并發就是這樣簡單,我們還可以啟動多個goroutine
- 這里使用了sync.WaitGroup來實現等待goroutine執行完畢
- 多次執行上面的代碼,會發現每次打印的數字的順序都不一致
- 這是因為10個goroutine是并發執行的,而goroutine的調度是隨機的
package mainimport ("fmt""sync"
)var wg sync.WaitGroupfunc hello(i int){defer wg.Done() //goroutine結束就登記-1fmt.PrintIn("Hello Goroutine!",i)
}func main() {for i :=0;i<10;i++ {wg.Add(1) //啟動一個goroutine就登記+1go hello(i)}wg.Wait() //等待所有登記的goroutine都結束
}
2、多協程統計素數
- 需求:要統計1-120000的數字中哪些是素數?goroutine for循環實現
- 協程?統計 1-30000
- 協程 統計 30001-60000
-
?協程 統計 60001-90000
-
協程 統計 90001-120000
-
start:(n-1)*30000+1 end:n*30000
package main
import ("fmt""sync""time"
)
var wg sync.WaitGroupfunc test(n int) {for num := (n-1)*30000 + 1; num < n*30000; num++ {if num > 1 {var flag = truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {fmt.Println(num, "是素數")}}}wg.Done()
}func main() {start := time.Now().Unix()for i := 1; i <= 4; i++ {wg.Add(1)go test(i)}wg.Wait()fmt.Println("執行完畢")end := time.Now().Unix()fmt.Println(end - start) //1毫秒
}