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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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