第一版(并行)
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
网友评论