美文网首页
go chan爬虫并行模式

go chan爬虫并行模式

作者: 哆啦在这A梦在哪 | 来源:发表于2018-07-09 17:00 被阅读8次

第一版(并行)

package main

import (
    "fmt"
    "sync"
)

var (
    time sync.WaitGroup
)

//worker用来控制chan队列中的每一个元素的执行
//keep控制主函数的阻塞,防止程序提前关闭
//循环worker中每一个成员,在循环中执行想要完成的逻辑程序
func work(id int, worker chan int) {
    for j := range worker {
        fmt.Println("start:", id, j)
        // time.Sleep(time.Second)
        fmt.Println("star your perform")
        fmt.Println("end:", id)

    }
    time.Done()
}

//开启协程的数目,协程中无数据,导致阻塞等待
//发送值,close停止接收,导致协程中逻辑运行
//丢弃keep中的元素,主线程退出
func main() {
    worker := make(chan int, 3)

    for i := 0; i < 5; i++ {
        time.Add(1)
        go work(i, worker)
        fmt.Println("go-then", i)
    }

    for i := 0; i < 5; i++ {
        worker <- i
    }
    close(worker)

    time.Wait()
}

运行过程解释:
(1)for i := 0; i < 5; i++ { time.Add(1) go work(i, worker) fmt.Println("go-then", i) }
解: 循环5次,开5个线程(5个工人在工厂流水线上工作)
通过管道(chan),将想要在协程处理的数据发送过去(管道就是流水线上的传送带,数据就是货物)
(2)```
func work(id int, worker chan int) {
for j := range worker {
fmt.Println("start:", id, j)
// time.Sleep(time.Second)
fmt.Println("star your perform")
fmt.Println("end:", id)

}
time.Done()

}```
解:每一个函数,其实就是一个协程(相当于一个工人在工作),中间的循环,就是不断处理从管道里面获得的数据(加工传送带中过来的货物),该函数相当于一个加工工厂

这里要注意:当开启协程的时候(运行到当前情况下),并没有开始工作,因为一开始管道中没有数据,协程会被阻塞
(3)

for i := 0; i < 5; i++ {
        worker <- i
    }
    close(worker)

    time.Wait()

解:开始给chan中传值,在(2)中接收到这里的值后,开始并行处理。所以,想要处理的数据从这里传递,逻辑也是从这里开始。传值完成后,就断开传送,免去干扰因素。
(4)

var time sync.WaitGroup

解:为什么要用这个变量?他也是用来控制并行的另一种方式,add为加一,Done为减一,wait会阻塞线程,只有当加和减持平的时候(加和减的数目相等),才会释放。因为在每一个协程循环完之后,如果不等待其他协程,那主函数(主线程)就直接关闭了,其他协程就无法完成工作

第三版(改进了全局变量,其他同上)

package main

import (
    "fmt"
    "sync"
)

//worker用来控制chan队列中的每一个元素的执行
//keep控制主函数的阻塞,防止程序提前关闭
//循环worker中每一个成员,在循环中执行想要完成的逻辑程序
func work(id int, worker chan int) {
    for j := range worker {
        fmt.Println("start:", id, j)
        // time.Sleep(time.Second)
        fmt.Println("star your perform")
        fmt.Println("end:", id)

    }

}

//开启协程的数目,5个工人一起工作,协程中无数据,导致阻塞等待
//发送值,close停止接收,导致协程中逻辑运行,任务的发出
func main() {
    var time sync.WaitGroup
    worker := make(chan int, 3)

    for i := 0; i < 5; i++ {
        time.Add(1)
        go func() {
            work(i, worker)
            time.Done()
        }()

        fmt.Println("go-then", i)
    }

    for i := 0; i < 300; i++ {
        worker <- i
    }
    close(worker)

    time.Wait()
}

代码实例使用地址:
https://gitee.com/stbadress/sync_waitground_user.git

相关文章

  • go chan爬虫并行模式

    第一版(并行) 运行过程解释:(1)for i := 0; i < 5; i++ { time.Add(1) go...

  • Go并发模型:并发协程chan的优雅退出

    Go并发模型:并发协程chan的优雅退出 go chan的使用

  • chan深入理解之源码分析

    chan的理解 chan用于协程间通信,结构体如下,代码位置为go/src/runtime/chan.go 从结构...

  • 【A Tour of Go 练习】:Web 爬虫

    在这个练习中,我们将会使用 Go 的并发特性来并行化一个 Web 爬虫。 修改 Crawl 函数来并行地抓取 UR...

  • Go中的chan

    go中的chan是动态的,因此千万不要把chan想象成slice切片类型的数据。 只要chan不close可以永远...

  • Go并发

    并发和并行 Go是并发语言,而不是并行语言。(Go is a concurrent language and no...

  • go小学鸡踩坑记录

    环境:go1.14.1 var ch chan int只是一个 nil ,并不能对 chan 进行 <- ch ,...

  • 记一次Python爬虫分享

    一、爬虫的目标 网址:http://www.gdgpo.gov.cn/queryMoreInfoList/chan...

  • Go建议(翻译)

    Go-advices 代码 go fmt 你的代码 多个if语句可以转换成switch 使用 chan struc...

  • go的chan中的锁

    chan是go中csp的关键,网上一直说chan性能一般,因为用到了锁,我就找来源码研究了一下 我们先看chan对...

网友评论

      本文标题:go chan爬虫并行模式

      本文链接:https://www.haomeiwen.com/subject/jeetpftx.html