跟着算法学GO(10)

156 阅读4分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看: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() 方法之后被执行。

示例如下

示例 1:

输入:nums = [1,2,3] 输出:"firstsecondthird" 解释: 有三个线程会被异步启动。输入 [1,2,3] 表示线程 A 将会调用 first() 方法,线程 B 将会调用 second() 方法,线程 C 将会调用 third() 方法。正确的输出是 "firstsecondthird"。

示例 2:

输入:nums = [1,3,2] 输出:"firstsecondthird" 解释: 输入 [1,3,2] 表示线程 A 将会调用 first() 方法,线程 B 将会调用 third() 方法,线程 C 将会调用 second() 方法。正确的输出是 "firstsecondthird"。

算法实现思路

这是一道简单难度的多线程题,不是很难,主要考察的是对于多线程开发的一个熟悉程度。

我们都知道多线程并发情况下,顺序打印时无序的,多少次运行就可能有多少次情况,在java的多线程情况下,我们一般会使用阻塞,挂起或是计数器的方式让多线程中的某单一线程停止。

但go语言是非常适合并发场景的开发语言,我们可以采用通道的方式来实现并发。

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,所以我就简单的写了一个小demo,我猜可能是用go写太简单,哈哈哈哈

go的并发

go设计的初衷中有一部分就是为了更好的适用于并发场景,所以go的并发开启相比于其他语言是比较简单的

我们只需要使用go 关键字即可开启一个goroutine用于并发。

goroutine 是轻量级线程。开启方式如下

 go func_name (参数1,参数2,……)
 

举个例子

 fo thread(a,b,c)
 

一个程序中可以开启多个goroutine,所有的goroutine共享同一个地址空间。

go的通道

go的通道是用来在goroutine线程之间传递数据的一种数据结构,通过操作符<-指定通道的方向,发送或接收。

默认情况下为双向通道(未指定方向)

通道的声明也很简单,算法的实现中也有所体现,如下

var secondChan = make(chan struct{})
var thirdChan = make(chan struct{})
var mainChan = make(chan struct{})

通过内置函数声明,声明的格式入下

var chan_name = make(chan type)

算法的实现中type格式空的结构体,因为不需要传递具体的数据,只需要形成顺序

struct {}

struct {}是一个无元素的结构体类型,通常在没有信息存储时使用。优点是大小为0,不需要内存来存储struct {}类型的值。

struct {} {}

struct {} {}是一个复合字面量,它构造了一个struct {}类型的值,该值也是空。

你以为结束了

小问题: 如何构建一个带缓冲区的通道?如何去遍历或是关闭通道?为什么通道能让线程顺序执行?

下一篇就讲,敬请期待

在这里插入图片描述

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