1. runtime
Go运行时的调度器使用 runtime.GOMAXPROCS 设置的值来确定需要使用多少个OS线程来同时执行Go代码。默认值是机器上的CPU核心数,也可以手动的指定。
执行下面的代码设置GOMAXPROCS的参数为1 ,此时是做完一个任务再做另一个任务。
设置GOMAXPROCS的参数为2,此时两个任务并行执行。
package main
import (
"fmt"
"runtime"
"time"
)
func sayHello() {
for i := 0; i < 20; i++ {
fmt.Println("say hello")
}
}
func sayHi() {
for i := 0; i < 20; i++ {
fmt.Println("say hi")
}
}
func main() {
//获取系统的cup核数
cup := runtime.NumCPU()
fmt.Println("cup:", cup)
//设置goroutine使用的cup数量
runtime.GOMAXPROCS(1)
go sayHello()
go sayHi()
time.Sleep(time.Second * 5)
}
2. goroutine 池
本质上goroutine 池是生产者消费者模型,能够有效的控制goroutine的数量。
下面是一个demo
package main
import (
"fmt"
"math/rand"
)
// Task 任务
type Task struct {
ID int
num int
}
// Result 存结果
type Result struct {
task *Task
sum int
}
//
func pool(num int, taskChan chan *Task, resultChan chan *Result) {
//num是创建goroutine的个数
for i := 0; i < num; i++ {
//匿名函数
go func(taskChan chan *Task, resultChan chan *Result) {
//获取 task 里面的 num,计算 num*num
for v := range taskChan {
r := &Result{
task: v,
sum: v.num * v.num,
}
resultChan <- r
}
}(taskChan, resultChan)
}
}
func main() {
//任务管道
taskChan := make(chan *Task, 64)
//结果管道
resultChan := make(chan *Result, 64)
pool(32, taskChan, resultChan)
//读取结果
go func(resultChan chan *Result) {
for r := range resultChan {
fmt.Printf("id:%d,num:%d,sum:%d\n", r.task.ID, r.task.num, r.sum)
}
}(resultChan)
var id int
//创建任务,并将任务放进任务管道
for {
id++
t := &Task{
ID: id,
//随机的生成 num
num: rand.Intn(200),
}
taskChan <- t
}
}