You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
3.8 KiB

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