九、goroutine和channel

进程和线程

A)进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单元

B)线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位

C)一个进程可以创建和撤销多个线程,同一个进程中的多个线程之间可以并发执行

  nginx是       进程    ----》Fork多个子进程   --》多线程   --》多进程程序

 

协程和线程

 

协程:独立的栈空间,共享堆内存,调度由用户自己控制,本质上有点类似于用户级线程,这些用户线程的调度也是自己实现的

线程:一个线程上可以跑多个协程,协程是轻量级的线程

线程分为用户态的线程和操作系统级别的线程

 

goroutine

 

package main

import (
   "fmt"
   "time"
)

func test(){
   var i int
   for {
      fmt.Println(i)
      time.Sleep(time.Second)
      i++
   }
}

func main(){
   go test()
   for{
      fmt.Println("i running in main")
      time.Sleep(time.Second) //必须要加上,防止main线程跑的太快看不清
   }
}

执行结果
D:\project>go build go_dev/day8/example
D:\project>example
i running in main
0
1
i running in main
i running in main
2
3
i running in main
i running in main
4
5
i running in main
i running in main
6

 

goroutine调度模型

 

M:系统里面的线程

P:调度器

G:协程 goroutine

 

1)可以看出上面的每个操作系统线程有4个协程执行,只不过有3个协程是在队列中执行

2)可以看出一个线程可以多个协程在跑

 

在1.8之前可以把程序设置到init函数里面,1.8以上不用设置cpu的核心数

 

如何设置golang运行的cpu核数

 

package main

import (
   "runtime"
   "fmt"
)

func main(){
   num := runtime.NumCPU()      //查找当前cpu的核心数量
   runtime.GOMAXPROCS(num)  //设置golang运行核数 这里结果为8
   fmt.Println(num)
}
运行结果
8
View Code

channel声明

var 变量名 chan 类型

var test chan int

var test chan string

var test chan map[string] string

var test chan stu

var test chan *stu

channl初始化使用make

变量名 = make (chan 类型 size)

创建map类型往channel里面添加数据

 

创建map类型往channel里面添加数据
package main

func main(){
   var mapchan chan map[string]string       //声明channel
   mapchan = make(chan map[string]string ,10)  //初始化channel
   m := make(map[string]string)          //初始化map
   m["stu01"]="stu01"

   mapchan <- m                      //往channel里面添加数据
}

创建struct,往channel里面添加数据
package main

type student struct{
   name string
}

func main(){
   var stuchan chan student
   stuchan = make(chan student,10)
   
   stu:=student{name:"stu01"}
   
   stuchan <- stu
   
}

指针形式添加到channel
package main

type student struct{
   name string
}

func main(){
   var stuchan chan *student
   stuchan = make(chan *student,10)

   stu:=student{name:"stu01"}

   stuchan <- &stu

}

channel超时处理

利用select来处理chan超时

 

for {
    select {
    case v := <-chan1:
        fmt.Println(v)
    case v := <-chan2:
        fmt.Println(v)
    default:
        time.Sleep(time.Second)
        fmt.Println("timeout...")
    }
}
View Code

 

time.After()定时器来做处理。

在time.After()计时器触发之前,底层计时器不会被垃圾收集器回收。

posted @ 2017-12-23 20:38  pi-pi-miao-miao  阅读(226)  评论(0编辑  收藏  举报