Go语言的通道(2)-缓冲通道

news/2024/7/5 7:42:29

有缓冲的通道相比于无缓冲通道,多了一个缓存的功能,如下图描述的一样:

从图上可以明显看到和无缓冲通道的区别,无缓冲必须两个Goroutine都进入通道才能进行数据的交换,这个不用,如果数据有,直接就能拿走。

package ChannelDemo

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

const (
    numberGoroutines = 4
    taskLoad         = 10
)

var bufferWg sync.WaitGroup

func init() {
    rand.Seed(time.Now().Unix())
}

func main() {
    //创建了一个10任务的缓冲通道
    tasks := make(chan string, taskLoad)
    bufferWg.Add(numberGoroutines)

    //创建4个Goroutine
    for gr := 1; gr <= numberGoroutines; gr++ {
        go worker(tasks, gr)
    }

    //向缓冲通道中放入数据
    for post := 1; post <= taskLoad; post++ {
        tasks <- fmt.Sprintf("Task : %d", post)
    }

    close(tasks)

    bufferWg.Wait()
}

func worker(tasks chan string, worker int) {
    defer bufferWg.Done()

    for {
        task, ok := <-tasks
        if !ok {
            fmt.Printf("Worker: %d : 结束工作 \n", worker)
            return
        }

        fmt.Printf("Worker: %d : 开始工作 %s\n", worker, task)

        //随机处理一下工作的时间
        sleep := rand.Int63n(100)
        time.Sleep(time.Duration(sleep) * time.Millisecond)

        fmt.Printf("Worker: %d : 完成工作 %s\n", worker, task)
    }
}

运行结果:

Worker: 3 : 开始工作 Task : 4
Worker: 2 : 开始工作 Task : 2
Worker: 1 : 开始工作 Task : 1
Worker: 4 : 开始工作 Task : 3
Worker: 4 : 完成工作 Task : 3
Worker: 4 : 开始工作 Task : 5
Worker: 2 : 完成工作 Task : 2
Worker: 2 : 开始工作 Task : 6
Worker: 3 : 完成工作 Task : 4
Worker: 3 : 开始工作 Task : 7
Worker: 1 : 完成工作 Task : 1
Worker: 1 : 开始工作 Task : 8
Worker: 3 : 完成工作 Task : 7
Worker: 3 : 开始工作 Task : 9
Worker: 1 : 完成工作 Task : 8
Worker: 1 : 开始工作 Task : 10
Worker: 4 : 完成工作 Task : 5
Worker: 4 : 结束工作
Worker: 3 : 完成工作 Task : 9
Worker: 3 : 结束工作
Worker: 2 : 完成工作 Task : 6
Worker: 2 : 结束工作
Worker: 1 : 完成工作 Task : 10
Worker: 1 : 结束工作 

因为哪一个worker先从通道中取值有系统自己进行调度的,所以每次运行的结果稍微不同,但是相同的是10个任务被4个协程有条不紊的完成了

注意:main中有一句代码 Close(tasks) 关闭通道的代码非常重要。当通道关闭后,goroutine 依旧可以从通道接收数据,但是不能再向通道里发送数据。

能够从已经关闭的通道接收数据这一点非常重要,因为这允许通道关闭后依旧能取出其中缓冲的全部值,而不会有数据丢失.

 

五、总结

无缓冲的通道保证同时交换数据,而有缓冲的通道不做这种保证。

转载于:https://www.cnblogs.com/dcz2015/p/10384067.html


http://www.niftyadmin.cn/n/928499.html

相关文章

Stream Collectors - summingInt

public static <T> Collector<T,​?,​Integer> summingInt​(ToIntFunction<? super T> mapper) public static <T> Collector<T,​?,​Long> summingLong​(ToLongFunction<? super T> mapper) public static <T> Collector…

为什么要应用编排,应用编排能做什么?

随着服务数量的增多&#xff0c;对服务配置的管理也提出了更高的要求。如何去管理诸多服务&#xff0c;不同环境中存在差异部分以及在系统运维阶段需要灵活变更的部分&#xff0c;这些都是服务配置管理中需要解决的问题。通过应用编排产生的编排模版保存了每个服务本身具体的部…

Stream Collectors - toCollection

public static <T,​C extends Collection<T>> Collector<T,​?,​C> toCollection​(Supplier<C> collectionFactory) 简述一下就是把集合中的元素转换成参数指定的集合类型进行保存。 看个例子&#xff1a; void test42() {List<Integer> …

mysql的limit优化

我们工作中可能会遇到大数据量&#xff08;假设上千万条&#xff09;分页的情况&#xff0c;执行的语句类似以下sql语句&#xff1a; select * from record limit 2000000,10 运行这条语句&#xff0c;时间保持在30秒左右&#xff0c;这样的性能是很差的。 那我们该怎么去优化它…

Stream Collectors - toList、toSet

public static <T> Collector<T,​?,​List<T>> toList() public static <T> Collector<T,​?,​Set<T>> toSet() 上面说完了toCollection这里接着说一下toLIst和toSet这两个方法。其实这两个方法的作用toCollection都能实现&#xff…

CentOS 7 安装 Nginx

导语 下面会用 yum 和编译两种方式来安装 Nginx。 yum 安装 使用 yum 命令&#xff0c;是相对简单的&#xff0c;输入 yum install -y nginx 显示如上界面&#xff0c;既是安装成功。接下来开启 Nginx 服务 配置文件在 /etc/nginx/nginx.conf&#xff0c; 代码文件地址在 /usr…

Stream Collectors - toConcurrentMap

和toMap方法一样&#xff0c;也根据参数的不同重载了3个方法&#xff0c;作用也和toMap一样&#xff0c;只不过操作的数据类型是ConcurrentMap&#xff0c;返回结果toMap是HashMap&#xff0c;ConcurrentMap返回的是ConcurrentHashMap&#xff0c;这个执行效率差一点但是是线程…

基于django搭建网站

Django 是由Python开发的一个免费的开源web框架&#xff0c;可以用于快速搭建网站。ps:web框架&#xff0c;也叫web应用框架&#xff0c;提供数据库接口&#xff0c;标准样板&#xff0c;会话管理等来支持网站&#xff0c;网络应用&#xff0c;服务的开发。安装django官网https…