go goroutine 学习笔记(三)

266 阅读1分钟
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
	}
}