|
|
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()
|
|
|
}
|