「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
生命不息,学习不止
题外话
大年初六啦,啊啊啊啊,明天就要上班了,我的春节假期这么快就要过去了,下次放假就是清明了。好远啊……假期快快来到我的身边吧
废话不多说,上货
LeetcCode-1114
1114. 按序打印
还是这道题,因为还有知识点没有讲完
题目如下:
给你一个类:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
三个不同的线程 A、B、C 将会共用一个 Foo 实例。
线程 A 将会调用 first() 方法 线程 B 将会调用 second() 方法 线程 C 将会调用 third() 方法 请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。
go实现算法
var secondChan = make(chan struct{})
var thirdChan = make(chan struct{})
var mainChan = make(chan struct{})
func first() {
fmt.Print("first")
secondChan <- struct{}{}
}
func second() {
<-secondChan
fmt.Print("second")
thirdChan <- struct{}{}
close(secondChan)
}
func third() {
<-thirdChan
fmt.Print("third")
mainChan <- struct{}{}
close(thirdChan)
}
func main() {
funcMap := map[int]func(){1: first, 2: second, 3: third}
for _, v := range funcMap {
go v()
}
<-mainChan
小问题回顾
小问题: 如何构建一个带缓冲区的通道?如何去遍历或是关闭通道?为什么通道能让线程顺序执行?
go通道缓冲区
带缓冲区的通道是指通道发送与接收数据的两方处于一个异步状态,数据暂存于通道的缓冲区,接收数据方可以选择在合适的时候接收数据。
但缓冲区的的大小不是无限的,当缓存区的数据存储满后,就会阻塞发送端发送数据,直到接收端接收数据,接收多少就可再向缓冲区中传入数据。
带缓存区的通道可以通过make()函数声明,如下
chan_name := make(chan int, 100)
make()函数中的第二个参数可以指定缓冲区的大小
举个例子如下
package main
import "fmt"
func main() {
// 这里我们定义了一个可以存储整数类型的带缓冲通道
// 缓冲区大小为2
ch := make(chan int, 2)
// 因为 ch 是带缓冲的通道,我们可以同时发送两个数据
// 而不用立刻需要去同步读取数据
ch <- 1
ch <- 2
// 获取这两个数据
fmt.Println(<-ch)//1
fmt.Println(<-ch)//2
}
go的通道的变量与关闭
go的通道也可以通过range 关键字来实现遍历,可以遍历通道读取到的数据,如下
v, _ := <-ch
我们也可以直接判定通道是否接收数据,如下
v, ok := <-ch
ok 为 false,就代表该通道接收数据完毕,此时可以使用内置函数close()来关闭通道,算法中也有所体现。
go通道阻塞
说了通道数据的接收与发送,大概多少就能明白为什么通道可以按指定顺序完成
从发送端来说,接收者未准备接收数据之前,一直都是阻塞的,同时,发送端未发送数据时,接收端也是阻塞的,这也就是算法中当first()未执行时其他线程不会执行的原因。
你以为结束了
小问题:goroutine为什么叫做轻量级线程?为什么go要使用它?具体实现是怎样的?
下一篇就讲,敬请期待
大家看完发现有什么错误,写在下面吧!跟我黑虎阿福比划比划!