package main
import (
"fmt"
"runtime"
)
func main() {
//goroutine 其实就是线程,但它比线程小,执行goroutine时只需较少的栈内存(4~5KB)
//c#中新建一个thread要分配1M的内存栈。所以,goroutine可以同时运行比较多的并发任务
//goroutine也正是因为这个原因比thread更易用、更高效、更轻便
//goroutine 通过关键字go实现,go funcName(参数)
//示例
//go sayHello("anther--Hello")
//sayHello("main--World")
//channels,channel类型,可以接收和发送数据
//必须使用make来创建channel并指定要发送到channel的值的类型
//ci := make(chan int) //可以发送int到ci这个channel(从这个channel取出的也是int类型)
//cs := make(chan string) //可以发送string到string这个channel(从这个channel取出的也是string类型)
//cf := make(chan interface{}) //可以发送interface{}到cf这个channel(从这个channel取出的也是interface{}类型)
//ch <- v //将v发送到channel ch
//v := <-ch //从channel中取值并赋值给v
//示例
/*
arr := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(arr[:len(arr)/2], c)
go sum(arr[len(arr)/2:], c)
x, y := <-c, <-c
fmt.Println(x, y, x+y)
*/
//Buffered Channels
//下面这个channel只有存4个int类型的数据,写入前4个时,不会阻塞 ,
//当写入第5个时,需要从chanel中读出1个,空出空间才能继续写入
//ch := make(chan int, 4)
//range、close 遍历和读取channel
//for i := range c能够不断的读取channel里面的数据,直到该channel被显式的关闭
//应该在生产者的地方关闭channel,而不是消费的地方去关闭它,这样容易引起panic
//消费方可以通过语法v, ok := <-ch测试channel是否被关闭。
//如果ok返回false,那么说明channel已经没有任何数据并且已经被关闭。
/*
ch := make(chan int, 10)
go fibonacci(cap(ch), ch)
for value := range ch {
fmt.Printf("%d\t", value)
}
*/
//select 类似于switch,选择一个符合条件的channel执行
//select 也有一个default:它是当channel阻塞(即没有空间)时执行
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacciSelect(c, quit)
//runtime中的goroutine函数
//退出当前执行的goroutine,但是defer函数还会继续调用
Goexit()
//sleep让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。
Gosched()
//返回 CPU 核数量
NumCPU()
//返回正在执⾏行和排队的任务总数
NumGoroutine()
//用来设置可以运行的CPU核数
GOMAXPROCS()
}
func sayHello(str string) {
for i := 0; i < 5; i++ {
//相当于c#中的sleep()
runtime.Gosched()
fmt.Println(str)
}
}
func sum(a []int, c chan int) {
sum := 0
for _, value := range a {
sum += value
}
c <- sum
}
func fibonacci(n int, c chan int) {
x, y := 1, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func fibonacciSelect(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
//default:
// 当c阻塞的时候执行这里
}
}
}