一 控制单个goroutine执行5次就结束
package main
// 编写一个程序,控制单个goroutine执行5次就结束
import (
"context"
"fmt"
"sync"
)
// 控制goroutine 执行5次结束
func main() {
// 定义一个运行次数变量
runCount := 0
//定义一个waitgroup,等待goroutine执行完成
var wg sync.WaitGroup
// 初始化context
parent := context.Background()
// 传入初始化的ctx,返回ctx和cancle函数
ctx, cancle := context.WithCancel(parent)
wg.Add(1) // 增加一个任务
go func() {
for {
select {
case <-ctx.Done():
fmt.Println("任务结束")
return
default:
fmt.Printf("任务执行了%d次\n", runCount)
runCount++
}
// 执行了5次,使用ctx的取消函数将任务取消
if runCount >= 5 {
cancle()
wg.Done() // goroutine执行完成
}
}
}()
wg.Wait() //等待所有任务完成
}
二 100个老太太抢10个鸡蛋
package main
import (
"fmt"
"sync"
)
// 100个老太太抢10个鸡蛋
func main() {
// 初始化一个waitgroup
var wg sync.WaitGroup
// 初始化一个可以放10个鸡蛋的篮子
var c=make(chan string,10)
// 把鸡蛋放入篮子中
for i:=0;i<10;i++{
c<-fmt.Sprintf("鸡蛋%d号",i)
}
// 启动100个gorouting,模拟100个老太太抢鸡蛋
for i := 0; i <100 ; i++ {
//开启抢鸡蛋的任务
wg.Add(1) // 增加一次wg
go func(num int) {
//模拟延迟
//time.Sleep(1*time.Second)
select {
case e:=<-c: // 从c中取出一个鸡蛋
fmt.Printf("第%d个老太太,抢到了:%s\n",num,e)
default:
// 什么都不处理,最后会继续执行wg.Done()
fmt.Printf("第%d个老太太抢破头,也没有抢到鸡蛋\n",num)
}
wg.Done() // 抢完通知wg结束
}(i)
}
wg.Wait()
}
三 生产者消费者场景
package main
import (
"fmt"
"time"
)
//包子铺老板生产包子,消费者吃包子
// 生产者消费者场景(1 生产者消费者数量均等;2 生产者多,消费者少;3 生产者少,消费者多)
// 定义一个全局channel,放包子的盘子
var c=make(chan string,10)
// 老板包包子(生产者)
func producer(index int) {
fmt.Printf("蒸了第【%d】号包子,放到盘子中\n",index)
c<-fmt.Sprintf("包子%d号",index)
}
// 顾客吃包子(消费者)
func consumer(index int) {
//bz:=<-c
select {
case bz:=<-c:
fmt.Printf("第%d号顾客,吃了:【%s】\n",index,bz)
default:
fmt.Printf("第%d号顾客,没吃到包子\n",index)
}
}
func main() {
//1 -------- 10个人生产包子,10个人吃包子
// 10个人生产
//for i := 0; i < 10; i++ {
// go producer(i)
//}
//// 10个人吃
//for i := 0; i < 10; i++ {
// go consumer(i)
//}
//time.Sleep(5*time.Second) // 不使用wg控制
//2 -------- 10个人生产包子,100个人吃包子
//10个人生产
//for i := 0; i < 10; i++ {
// go producer(i)
//}
//// 100个人吃
//for i := 0; i < 100; i++ {
// go consumer(i)
//}
//time.Sleep(5*time.Second) // 不使用wg控制
//3 100个人生产,10个人吃包子
// 100个人生产
for i := 0; i < 100; i++ {
go producer(i)
}
// 10个人吃
for i := 0; i < 10; i++ {
go consumer(i)
}
time.Sleep(5*time.Second) // 不使用wg控制
}
四 练习题
题目:某工厂有A、B、C三辆厨房工程车,A车上能清洗材料,B车
上能加工材料, C车上能装载材料;三辆工程车能边行驶边清洗/加
工/装载材料,每辆车上有3个工人;最初的原始材料有D1、D2、
D3三种材料,每种材料的清洗耗时比例为6:3:3 ,每种材料的加工/
装载耗时皆为1:1:1 ,每种材料的数量一致;材料的处理顺序为, 清
洗->加工->装载;车辆之间材料进行交互,需要保持比较近的相对
距离
要求:这三辆车需要将处理完的原材料,尽快送达商家手里。请问
如何分配比较好?
条件
//1 ABC三辆工程车
//2 A清洗 B加工 C装载
//3 三辆工程车边行驶,边 清洗/加工/装载材料,每辆车有三个工人
//4 有原始材料:D1,D2,D3,每种材料清洗耗时:6:3:3
//5 每种材料加工,装载耗时:1:1:1,材料数量一致
约束
//1 材料处理顺序为:清洗---》加工---》装载
//2 车辆之间材料进行交互,要保持相对近的距离
要求
// 处理完的原材料,尽快送到商家手中
goroutine
//1 三辆工程车分别为3个goroutine
//2 三辆车,3个func,分别执行不同功能--》A车:funcA;B车:funcB;C车:funcC
//3 每个func内部有3个子goroutine,代表3个工人
//4 funcB和funcC步骤的材料处理时间相等,因此每个工人负责对应的材料堆即可
//5 funcA材料耗时不一,对材料重新整合,将每种材料3等分,每个工人分到三分之一,进行加工
channal
// 材料的传输:funcA==》funcB==》funcC
// 最后由c运送给商家
注意
// 三辆工程车一起开出
package main
import (
"fmt"
"sync"
)
var (
wg sync.WaitGroup // 管理每个车中3个工人的完成
globalWg sync.WaitGroup // 管理3两车的完成
ch = make(chan []string, 3) // 用来在三个车(goroutine)之间传递材料
)
// 工程车A:清洗材料
func funcA(elements []string) { // 传入材料
// 把传入的材料进行切分
for index,element:=range elements{
wg.Add(1)
go func(element string,index int) {
elements[index]=clean(element)
wg.Done()
}(element,index)
}
wg.Wait()
ch<-elements
fmt.Println(len(ch))
globalWg.Done()
}
// 工程车B:加工材料
func funcB() {
// 接收材料
var elements =[]string{}
for {
select {
case elements =<-ch: // 接收到某种材料,就结束死循环,开始处理,接收不到,继续等待接收
fmt.Println("收到了")
break
default:
fmt.Println("没收到")
fmt.Println(len(ch))
continue
}
}
// 分配3个工人开始加工材料
for index,element:=range elements{
wg.Add(1)
go func(element string,index int) {
elements[index]=cure(element)
wg.Done()
}(element,index)
}
wg.Wait()
ch<-elements
globalWg.Done()
}
// 工程车C:运载材料
func funcC() {
// 接收材料
var elements =[]string{}
for {
select {
case elements =<-ch: // 接收到某种材料,就结束死循环,开始处理,接收不到,继续等待接收
break
default:
continue
}
}
// 分配3个工人开始运输材料
for index,element:=range elements{
wg.Add(1)
go func(element string,index int) {
elements[index]=carry(element)
wg.Done()
}(element,index)
}
wg.Wait()
globalWg.Done()
}
func main() {
var elements = []string{"材料1", "材料2", "材料3"}
globalWg.Add(1)
go funcA(elements)
globalWg.Add(1)
go funcB()
globalWg.Add(1)
go funcC()
globalWg.Wait()
//elements=<-ch
fmt.Println(elements)
}
// 清洗功能
func clean(element string) string {
return fmt.Sprintf("材料【%s】被清洗了---》", element)
}
// 加工功能
func cure(element string) string {
return fmt.Sprintf("材料【%s】被加工了---》", element)
}
// 运输功能呢
func carry(element string) string {
return fmt.Sprintf("材料【%s】被运输了---》", element)
}