练习题1

一 控制单个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)
}

posted @ 2022-03-19 22:21  刘清政  阅读(134)  评论(0编辑  收藏  举报