Go并发编程--通过channel实现流水线作业模型

概述

流水线作业,是多个线程协作,就像加工车间的传送带,每个线程完成一项任务,然后把结果发送给下一个线程,直到所有线程的任务完成,一个“产品”的加工过程就完成了。
通过Go的channel,可以很方便的实现流水线作业。

流水线作业的实现

在linux系统编程中,一般来说流水线作业的线程数是固定的,我们模拟的这个场景,假设有几个固定的goroutine共同协作来完成一个字符串的处理,goroutine之间通过channel来进行数据传递,各个goroutine主要进行的操作如下:
1. 第1个goroutine:一个字符串全部改成小写
2. 第2个:在该字符串前面添加HELLO: 字样
3. 第3个:统计字数,并打印字符串
当然,你可以把这些操作替换成任意你想完成的任务,就可以使用了。

代码实现

package main

import (
    "fmt"
    "os"
    "strings"
    "time"
)

//
// 模拟流水线作业:
// 1. 一个字符串全部改成小写
// 2. 在该字符串前面添加HELLO: 字样
// 3. 统计字数,并打印字符串
//

func starter(ch1 chan string) {
    for i := 0; i <10; i++ {
        v := fmt.Sprintf("HoVer: %d", i)
        fmt.Fprintf(os.Stderr, "starter send: %s\n", v)
        ch1 <- v
        time.Sleep(1e9)
    }
}

func lowString(ch1 chan string, ch2 chan string) {
    for {
        str := <- ch1
        res := strings.ToLower(str)
        ch2 <- res
    }
}

func addString(ch2 chan string, ch3 chan string) {
    for {
        str := <- ch2
        res := fmt.Sprintf("HELLO: %s", str)
        ch3 <- res
    }
}

func getResult(ch3 chan string) {
    for {
        v := <- ch3
        len := len(v)
        fmt.Fprintf(os.Stderr, "len=%d, result=%s\n", len, v)
    }
}

func main() {
    ch := make(chan string)
    go starter(ch)

    ch1 := make(chan string)
    go lowString(ch, ch1)

    ch2 := make(chan string)
    go addString(ch1, ch2)
    go getResult(ch2)

    time.Sleep(100e9)
}

总结

通过channel(容量为1)的数据传递可以很方便的实现流水线的模型,这样每个goroutine就可以只专注于完成自己的那一部分任务,从而把一个复杂的任务分解成相互依赖的小任务来进行处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值