跟着算法学GO(11)

110 阅读3分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

生命不息,学习不止

题外话

大年初六啦,啊啊啊啊,明天就要上班了,我的春节假期这么快就要过去了,下次放假就是清明了。好远啊……假期快快来到我的身边吧

image.png

废话不多说,上货

在这里插入图片描述

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 int2)

        // 因为 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要使用它?具体实现是怎样的?

下一篇就讲,敬请期待

在这里插入图片描述

大家看完发现有什么错误,写在下面吧!跟我黑虎阿福比划比划! 在这里插入图片描述