代码改变世界

go中的并发(goroutine)

2013-04-04 23:19  Yang-Onion  阅读(621)  评论(0编辑  收藏  举报
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阻塞的时候执行这里
		}
	}
}

 

home page tracking
NutriSystem Diet