package goConcurrency import ( "fmt" "github.com/panjf2000/ants/v2" "log" "runtime" "sync" "time" ) func GoroutineGo() { // 定义输出奇数的函数 printOdd := func() { for i := 1; i <= 10; i += 2 { fmt.Println(i) time.Sleep(100 * time.Millisecond) } } // 定义输出偶数的函数 printEven := func() { for i := 2; i <= 10; i += 2 { fmt.Println(i) time.Sleep(100 * time.Millisecond) } } // 顺序调用 //printOdd() //printEven() // 在 main goroutine 中,开启新的goroutine // 并发调用 go printOdd() go printEven() // 典型的go //go func() {}() //func() {}() // main goroutine 运行结束 // 内部调用的goroutine也就结束 time.Sleep(time.Second) } // 测试时,需要定义对应的测试文件,例如goroutine_test.go // 增加单元测试函数: //file:goroutine_test.go //package goConcurrency // //import "testing" // //func TestGoroutineGo(t *testing.T) { // GoroutineGo() //} // 输出测试结果 //goConcurrency> go test -run TestGoroutineGo //1 //2 //4 //3 //5 //6 //8 //7 //9 //10 //PASS //ok goConcurrency 1.052s func GoroutineWG() { // 1. 初始化 WaitGroup wg := sync.WaitGroup{} // 定义输出奇数的函数 printOdd := func() { // 3.并发执行结束后,计数器-1 defer wg.Done() for i := 1; i <= 10; i += 2 { fmt.Println(i) time.Sleep(100 * time.Millisecond) } } // 定义输出偶数的函数 printEven := func() { // 3.并发执行结束后,计数器-1 defer wg.Done() for i := 2; i <= 10; i += 2 { fmt.Println(i) time.Sleep(100 * time.Millisecond) } } // 在 main goroutine 中,开启新的goroutine // 并发调用 // 2, 累加WG的计数器 wg.Add(2) go printOdd() go printEven() // 其他的goroutine中wait go func() { wg.Wait() fmt.Println("Wait in inner goroutine") }() // main goroutine 运行结束 // 内部调用的goroutine也就结束 // 4. 主goroutine等待 wg.Wait() fmt.Println("after main wait") } func GoroutineNum() { // 1. 统计当前存在的goroutine的数量 go func() { for { fmt.Println("NumGoroutine:", runtime.NumGoroutine()) time.Sleep(500 * time.Millisecond) } }() // 2. 启动大量的goroutine for { go func() { v := make([]int, 1024) _ = v fmt.Println("in goroutine") time.Sleep(100 * time.Second) }() } } func GoroutineAnts() { // 1. 统计当前存在的goroutine的数量 go func() { for { fmt.Println("NumGoroutine:", runtime.NumGoroutine()) time.Sleep(500 * time.Millisecond) } }() // 2. 初始化协程池,goroutine pool size := 1024 pool, err := ants.NewPool(size) if err != nil { log.Fatalln(err) } // 保证pool被关闭 defer pool.Release() // 3. 利用 pool,调度需要并发的大量goroutine for { // 向pool中提交一个执行的goroutine err := pool.Submit(func() { //v := make([]int, 1024) //_ = v //fmt.Println("in goroutine") time.Sleep(100 * time.Second) }) if err != nil { log.Fatalln(err) } } } func GoroutineRandom() { wg := sync.WaitGroup{} // 同时启动多个goroutine输出不同的数字 workerNum := 10 wg.Add(workerNum) for i := 0; i < workerNum; i++ { go func(n int) { wg.Done() fmt.Println(n) }(i) } wg.Wait() } func GoroutineSched() { wg := sync.WaitGroup{} wg.Add(2) // 设置为1个P在调度G runtime.GOMAXPROCS(1) // 单线程模式 // 输出奇数 max := 100 go func() { defer wg.Done() for i := 1; i <= max; i += 2 { fmt.Print(i, " ") // 主动让出 runtime.Gosched() // 增加执行时间 //time.Sleep(1 * time.Millisecond) } }() // 输出偶数 go func() { defer wg.Done() for i := 2; i <= max; i += 2 { fmt.Print(i, " ") // 主动让出 runtime.Gosched() // 增加执行时间 //time.Sleep(1 * time.Millisecond) } }() wg.Wait() }