golang使用channel通道实现非阻塞队列和超时阻塞队列

golang的通道(chan)可分为不带缓存的通道和带缓存的通道。用make函数创建通道的时候,如果不指定缓存大小,创建的就是不带缓存的通道。

向通道中放入数据的一端可以称为生产者,从通道获取数据的一端可以称为消费者。
不带缓存的通道,在通道任一一端没有准备就绪之前,另一端就会产生阻塞。

生产者往channel写数据,但是channel满了,导致生产者阻塞。

Channel是Golang中非常重要的数据结构, golang的channel读或写是会造成阻塞的,但是可以用select的多路复用解决这个问题。

select的多路复用(不阻塞读channel、非阻塞写入channel),可以用于检测某个通道是否满了,是否是空的

golang select default continue_Go并发(四):select篇
参考URL: https://blog.csdn.net/weixin_39520393/article/details/109969948

golang select default
select存在default的话,在case不命中的情况下,会直接进入default分支,协程一样会结束,不会阻塞住。

不阻塞读channel(也可以加上超时)

func readChan(c chan int) (int, error) {
	select {
	case num := <-c:
		return num, nil
	default:
		return 0, errors.New("chan do not have data")
// 加上超时时间
func readChanWithTimeout(c chan int) (int, error) {
	timeout := time.NewTimer(time.Microsecond * 100)
	select {
	case num := <-c:
		return num , nil
	case <-timeout.C:
		return 0, errors.New("read chan time out")

非阻塞写入channel(也可以加上超时)

func writeChan(num int, c chan int) error {
	select {
	case ch <- num:
		return nil
	default:
		return errors.New("chan is full")
// 加上超时时间
func writeChanWithTimeout(num int, c chan int) error {
	timeout := time.NewTimer(time.Microsecond * 100)
	select {
	case c <- num:
		return nil
	case <-timeout.C:
		return errors.New("write chan time out")

实现非阻塞队列

在golang中,基本的channel读写操作都是阻塞的,如果你想要非阻塞的,可以使用如下示例:

即只要在select中加入default,阻塞立即变成非阻塞:

package main
import "fmt"
func main() {
    messages := make(chan string)
    signals := make(chan bool)
    select {
    case msg := <-messages:
        fmt.Println("received message", msg)
    default:
        fmt.Println("no message received")
    msg := "hi"
    select {
    case messages <- msg:
        fmt.Println("sent message", msg)
    default:
        fmt.Println("no message sent")
    select {
    case msg := <-messages:
        fmt.Println("received message", msg)
    case sig := <-signals:
        fmt.Println("received signal", sig)
    default:
        fmt.Println("no activity")
				
golang中,基本的channel读写操作都是阻塞的,如果你想要非阻塞的,可以使用如下示例: 即只要在select中加入default,阻塞立即变成非阻塞: package main import "fmt" func main() { messages := make(chan string) signals := make(chan ...
在学习过程中发现redis的zset还可以用来实现轻量级的延时消息队列功能,虽然可靠性还有待提高,但是对于一些对数据可靠性要求不那么高的功能要求完全可以实现。本次主要采用了redis中zset中的zadd, zrangebyscore 和 zdel来实现一个小demo。 提前准备 安装redis, redis-go 因为用的是macOS, 直接 $ brew install redis $ go get github.com/garyburd/redigo/redis 又因为比较懒,生成任务的唯一id时,直接采用了bson中的objectId,所以: $ go get gopkg. 这周姐姐入职了新公司,老板想探探他的底,看了一眼他的简历,呦呵,精通kafka,这小姑娘有两下子,既然这样,那你写一个消息队列吧。因为要用go语言写,这可给姐姐愁坏了。赶紧来求助我,我这么坚贞不屈一人,在姐姐的软磨硬泡下还是答应他了,所以接下来我就手把手教姐姐怎么写一个消息队列。下面我们就来看一看我是怎么写的吧~~~。 本代码已上传到我的github: 有需要的小伙伴,可自行下载,顺便给个小星星吧~~~ 什么是消息队列 姐姐真是把我愁坏了,自己写的精通kafka,竟然不知道什么是消息队列,于是
chan数据结构 channelGolang语言层面提供的goroutine间的通信方式,比Unix管道更易用也更轻便。channel主要用于进 程内各goroutine间通信,如果需要跨进程通信,建议使用分布式系统的方法来解决。 本章从源码角度分析channel实现机制,实际上这部分源码常简单易读。 chan数据结构 从数据结构可以看出channel由队列、类型信息、goroutine等待队列组成,下面分别说明其原理。 chan内部实现了一个环形队列作为其缓冲区,队列的长度是创建cha
1、开一个协程writeDataToFile,随机生成30~1000个数据,存放到文件中 2、当writeDataToFile完成写1000个数据到文件后,让sort协程从文件中读取1000个文件,并完成排序,重新写入到另外一个文件中 package main import ( "encoding/json"
Golang 有多种消息队列可供选择,其中比较流行的有以下几种: 1. RabbitMQ:RabbitMQ 是一款开源的 AMQP 消息队列系统,支持多种编程语言,包括 Golang。它提供了高可用性、可靠性和可扩展性,适合于处理大量消息和实时数据。 2. Kafka:Kafka 是一个分布式的流处理平台,也是一个高吞吐量分布式消息系统。它可以处理大量的消息,并提供了持久化和可扩展性等优点。 3. NSQ:NSQ 是一个实时分布式消息系统,具有高可用性和可伸缩性。它可以处理高并发量的消息,同时支持负载均衡和故障恢复等功能。 4. NATS:NATS 是一个高性能、轻量级的消息系统,适合于处理大量的消息和实时数据。它提供了基于主题的发布/订阅模式和点对点模式,支持多种编程语言,包括 Golang。 以上这些消息队列都可以在 Golang使用,具体选择哪种取决于你的需求和场景。