1.实现go程
go程的实现十分简单,只需要在该函数前加上关键字go,即可成为一个gotoutine
package main
import "fmt"
func goRoutine1(){
fmt.Println("11111111111111111")
}
func goRoutine2(){
fmt.Println("2222222222222222")
}
func main() {
go goRoutine1()
go goRoutine2()
fmt.Println("main")
for {
;
}
}
2.runtime.Gosched
用于让出CPU时间片,让出当前goroutine的执行权限,调度器安排其它等待的任务运行,并在下次某个时候从该位置恢复执行。这就像跑接力赛,A跑了一会碰到代码runtime.Gosched()就把接力棒交给B了,A歇着了,B继续跑。简单来说 就是,调用runtime.Gosched的go程,执行效率变低 ,其他程序执行变快。
runtime.Gosched()
3.GOexit
调用此函数会立即使当前的goroutine的运行终止(终止协程),而其它的goroutine并不会受此影响。runtime.Goexit在终止当前goroutine前会先执行此goroutine的还未执行的defer语句。请注意千万别在主函数调用runtime.Goexit,因为会引发panic。
runtime.Goexit()
4.runtime.GOMAXPROCS()
用来设置可以并行计算的CPU核数最大值,并返回之前的值。默认此函数的值与CPU逻辑个数相同,即有多少个goroutine并发执行,当然可以设置它,它的取值是1~256。最好在主函数在开始前设置它,因为设置它会停止当前程序的运行。GO默认是使用一个CPU核的,除非设置runtime.GOMAXPROCS。那么在多核环境下,什么情况下设置runtime.GOMAXPROCS会比较好的提高速度呢?适合于CPU密集型、并行度比较高的情景。如果是IO密集型,CPU之间的切换也会带来性能的损失。
n := runtime.GOMAXPROCS(4)
//n为上一次调用时的核数 首次为默认值1
runtime包其他功能如垃圾回收等,请参考完整说明 :https://studygolang.com/articles/13994?fr=sidebar
channel 可以把它看成一个管道,是 goroutine 之间通信的一种方式。
ch := make(chan TYPE CAPCITY)
CAPCITY==0 --> 无缓冲阻塞channel
CAPCITY > 0 --> 有缓冲无阻塞channel
//ch:=make(chan int,3)
ch := make(chan int)
// write to channel
ch <- x
// read from channel
x <- ch
// another way to read
x = <- ch
利用无缓冲channel阻塞的特点,可以实现go程之间顺序的控制
在主函数中定义一个无缓冲channel,在主函数中进行读channel操作,在go程逻辑执行完以后进行写channel操作,即可实现主函数等待所以go程执行完以后再退出。
package main
import (
"fmt"
"runtime"
)
func goRoutine1(ch chan int){
ch <- 1
for i:=0;i<10;i++{
fmt.Println("111111111111111111111111111111")
}
}
func goRoutine2(ch chan int){
x:=<-ch
fmt.Printf("chennel %d ---------------\n",x)
for i:=0;i<10;i++{
if i==5{
runtime.Goexit()
}
fmt.Println("2222222222222222")
}
}
func main() {
ch:=make(chan int)
go goRoutine1(ch)
go goRoutine2(ch)
for i:=0;i<10;i++{
runtime.Gosched()
fmt.Println("main");
}
}
//先执行完goroutine1 再执行goroutine2
//chennl中剩余未读取的个数
len(ch)
//chennl长度
caps(ch)
无缓冲channel中len和caps为0
ch := make(chan int)
close(ch)
package main
import (
"fmt"
"runtime"
)
func goRoutine1(ch chan int){
for i:=0;i<10;i++{
ch<-i
}
close(ch)
}
func main() {
ch:=make(chan int)
go goRoutine1(ch)
for{
if num,ok:=<-ch;ok==true{
fmt.Println(num)
}else {
break;
}
}
}
//或者
for num:=range ch{
fmt.Println(num)
}
var ch1 chan<- int
var ch2 <-chan int
select 用法类似与 IO 多路复用,可以同时监听多个 channel 的消息状态,看下面的例子
select {
case <- ch1:
...
case <- ch2:
...
case ch3 <- 10;
...
default:
...
}