ZVVQ代理分享网

golang并发编程中的管道与消息队列(go协程使用)

作者:zvvq博客网
导读管道和消息队列是 go 中用于 goroutine 通信的原语。管道是无缓冲通道,立即传递数据;消息队列是缓冲通道,允许存储多个消息。实战案例中,管道可用于并行处理任务,如将一组任务

管道和消息队列是 go 中用于 goroutine 通信的原语。管道是无缓冲通道,立即传递数据;消息队列是缓冲通道,允许存储多个消息。实战案例 中,管道可用于并行处理任务,如将一组任务发送到管道并使用 goroutine 池并行处理。

Go 中的管道与消息队列

在 Go 中,管道和消息队列是用于 goroutine 之间通信的两个基本原语。

管道

go语言免费”;

管道是无缓冲的通信通道,数据会立即从写入端传递到读取端。管道通常用于在 goroutine 之间传递小块数据。

创建管道:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

package main

import "fmt"

func main() {

// 创建一个管道

ch := make(chan int)

// 写入数据

ch <- 42

// 读取数据

v := <-ch

fmt.Println(v) // 输出 42

}

消息队列

消息队列是一种缓冲的通信通道,允许在写入端和读取端之间存储多个消息。这使得 goroutine 可以按自己的节奏发送和接收消息,而不必担心丢失或阻塞。

使用内置的 sync.Mutex 和 sync.Cond 创建一个简单的消息队列:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

package main

import (

"fmt"

"sync"

"time"

)

func main() {

// 创建一个消息队列

var (

queue = []int{}

mu    sync.Mutex

cond  sync.Cond

)

// 启动一个生产者 goroutine

go func() {

for {

mu.Lock()

queue = append(queue, 42)

cond.Signal()

mu.Unlock()

time.Sleep(time.Second)

}

}()

// 启动一个消费者 goroutine

go func() {

for {

mu.Lock()

for len(queue) == 0 {

cond.Wait()

}

v := queue[0]

queue = queue[1:]

mu.Unlock()

fmt.Println(v) // 输出 42

}

}()

// 等待 goroutine 退出

time.Sleep(time.Second 5)

}

实战案例 :并行处理任务

管道或消息队列可以用于并行处理任务。以下是一个示例,说明如何使用管道并行处理一组任务:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

package main

import (

"fmt"

"sync"

)

func main() {

// 定义任务

tasks := []int{1, 2, 3, 4, 5}

// 创建管道

ch := make(chan int)

// 启动 goroutine 池来处理任务

var wg sync.WaitGroup

for i := 0; i < 4; i++ {

wg.Add(1)

go func(ch chan int) {

for task := range ch {

fmt.Println(task)

}

wg.Done()

}(ch)

}

// 将任务发送到管道

for _, task := range tasks {

ch <- task

}

// 关闭管道

close(ch)

// 等待 goroutine 池完成

wg.Wait()

}

以上就是golang并发编程中的管道与消息队列的详细内容,更多请关注其它相关文章!