阅读 384
收藏 13
2017-05-18
原文链接:blog.sodroid.com
转载请注明本文地址,感谢 :)
本文不详细解释这三个名词的意思,下面有一篇文章,不懂的同学可以参考看看。
- Goroutine 奉行通过通信来共享内存,而不是共享内存来通信
- 使用goroutine很简单,只需要用到一个关键字go,我们用一段代码来示例一下如何使用go关键字
package main
import (
"fmt"
)
func main() {
go Goroutine()
}
func Goroutine() {
fmt.Println("Goroutine")
}
因为我们当前的程序,只是一个单线程的程序,main函数只要执行完毕后,就不会再管其他线程在做什么事情了,程序自动退出。 然后我们想到了一个办法,加一个sleep函数,让main函数等待Goroutine函数执行完毕后再退出。
更改后的代码如下:
package main
import (
"fmt"
"time"
)
func main() {
go Goroutine()
time.Sleep(3 * time.Second)
}
func Goroutine() {
fmt.Println("Goroutine")
}
channel使用make创建
chann := make(chan bool)
往channel中传入数据
chann <- true
输出channel中的数据
<- chann
接着我们改进上面使用Sleep方式的代码,换成使用channel的版本
package main
import (
"fmt"
)
func main() {
chann := make(chan bool)
go func() {
fmt.Println("Goroutine")
chann <- true
}()
<- chann
}
<-chann
,这实际上是起到了阻塞的作用,当匿名函数里面的业务没有执行完并讲true传入channel中的时候,这个程序是不会退出的,匿名函数外面会一直在等待。当匿名函数里面执行到了chann <- true
,也就是将true传入了channel的时候,就不会继续阻塞,这时候程序就会结束。这就是channel的作用。package main
import (
"fmt"
)
func main() {
chann := make(chan bool)
go func() {
fmt.Println("Goroutine")
chann <- true
close(chann) //关闭channel
}()
for v := range chann {
fmt.Println(v)
}
}
ChannelType = ("chan" | "chan" "<-" | "<-" "chan")
chan T
//可以接收也可以发送chan <- bool
//可以发送bool类型的数据<- chan bool
//可以接收int类型的数据无缓冲Channel
chann := make(chan int)
缓冲Channel
chann := make(chan int,100)
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) // 设置线程数为当前计算机的CPU数
chann := make(chan bool, 10)
for i := 0; i < 10; i++ {
go Go(chann, i)
}
for i := 0; i < 10; i++ {
<-chann
}
}
func Go(chann chan bool, index int) {
a := 1
for i := 0; i < 100000000; i++ {
a += 1
}
fmt.Println(index, a)
chann <- true
}
wg.Done()
,当10个任务都完成的时候,程序自动退出。package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
wg :=sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
go Go(&wg, i)
}
wg.Wait()
}
func Go(wg *sync.WaitGroup, index int) {
a := 1
for i := 0; i < 100000000; i++ {
a += 1
}
fmt.Println(index, a)
wg.Done()
}
select 用于多个channel监听并收发消息,当任何一个case满足条件则会执行,若没有可执行的case,就会执行default,如果没有default,程序就会阻塞。
package main
import (
"fmt"
"time"
)
func main() {
chann := make(chan int)
go enqueue(chann)
for {
select {
case v, ok := <-chann:
if ok {
fmt.Println(v)
} else {
fmt.Println("close")
return
}
default:
fmt.Println("waiting")
}
}
}
func enqueue(chann chan int) {
time.Sleep(3 * time.Second)
chann <- 1
close(chann)
}