简单看懂GO语言并发
2017-08-03 00:00
489 查看
并发基础
GO语言处理并发非常简单,使用关键词“go”即可。创建main.go文件,内容如下:
package main func main() { go print(1) }
这是一个非常简单的并发例子。运行 go run main.go,你会发现什么也不会输出。为什么?因为没等print执行,主程就退了。
我们把代码修改下:
package main import "time" func main() { go print(1) time.Sleep(time.Second) }
这里停了一秒,使得print有足够的时间输出后结束。假设print执行超过一秒钟,或者我们压根不知道print要执行多少时间,这是后我们就要要到“channel”啦。
package main import ( "fmt" "time" ) func main() { done := make(chan bool) go Print(1, done) for { <-done break } } func Print(args interface{}, done chan bool) { time.Sleep(time.Second * 3) fmt.Println(args) done <- true }
无论我们怎么调整sleep的参数,程序都会等待print输出后才结束。到这里我们想如果Print 3秒钟后还没执行我们就要退出了,这里就可以用到channel的一个超时处理方式:
package main import ( "fmt" "time" ) func main() { done := make(chan bool) isTimeOut := make(chan bool) go Print(1, done) go func(){ time.Sleep(time.Second*3) isTimeOut <- true }() for { select { case <-done: return case <-isTimeOut: println("timeout.") return } } } func Print(args interface{}, done chan bool) { time.Sleep(time.Second * 5) fmt.Println(args) done <- true }
这里go run main.go输出"timeout."。我们可以设置缓冲,如:
result := make(chan int,10)
result一开始会存入10个元素,阻塞直到result的元素被取出且小于10后才能再往result写入数据。
并发应用
使用go并发我们可以进行任务分发:package main import ( "fmt" ) func main() { result := make(chan int) rlt := 0 go Sum(1, 50, result) go Sum(51, 100, result) //把两次写入到result的值取出来求和 for i := 1; i <= 2; i++ { rlt += <-result } fmt.Println(rlt) } func Sum(start, end int, result chan int) { sum := 0 for i := start; i <= end; i++ { sum += i } result <- sum }
这里计算1+2+3+..+100的和,并发两个进程处理。当然这里为了演示不考虑算法问题了。
使用GO并发构建工作池,工作池就是能进行特定功能处理的“工人”的集合。这里的“工人”可以理解为我们封装好的函数比如上面sum。看下简单的一个示例:
package main import ( "fmt" ) func main() { start, end := make(chan int), make(chan int) //启动有五个工人的工作池 for i := 0; i <= 4; i++ { go Sum(i, start, end) } //发送任务给工作池中工人处理 for i := 1; i <= 5; i++ { start <- i * 5 end <- i * 10 } } func Sum(worker int, start, end chan int) { sum := 0 s := <-start e := <-end for i := s; i <= e; i++ { sum += i } fmt.Println("worker ", worker, " -> ", sum) }
每次go run main.go输出的顺序,结果可能都不一样:
worker 4 -> 45 worker 2 -> 360 worker 1 -> 165 worker 3 -> 630 worker 0 -> 975
worker 4 -> 45 worker 1 -> 165 worker 3 -> 360 worker 0 -> 630 worker 2 -> 975
可以看出,只要哪个“工人”通道中获取到需要计算的值,谁就先处理。
相关文章推荐
- Go语言并发编程简单入门
- Go语言基础学习三-简单的代码分析(并发)
- go语言 grequests+goquery 简单爬虫,使用多协程并发爬取
- 28.笔记go语言——并发简单示例
- GO语言构建高并发分布式系统实践
- go语言编写,简单聊天室程序 1
- Go语言并发之美
- Go语言实现简单的留言本
- Go语言并发与并行学习笔记(二)
- Go语言远程执行ssh命令简单封装(支持带交互命令)
- Go语言_并发篇
- Go语言-并发
- Go语言并发之美
- go语言坑之并发访问map
- Go语言 并发篇
- 在 Go 语言中,正确的使用并发
- Go语言并发与并行学习笔记(三)
- Go语言并发机制初探
- go语言并发编程
- Go语言web简单配置