• 九、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()计时器触发之前,底层计时器不会被垃圾收集器回收。

  • 相关阅读:
    支付宝支付私钥和公钥创建
    (五)Maven中的聚合和继承
    Windows 下Nexus搭建Maven私服
    (四)Maven中的仓库
    zookeeper安装和使用 windows环境
    (一)Redis之简介和windows下安装radis
    (错误) Eclipse使用Maven创建Web时错误
    (三)引用中央仓库中不存在的jar包
    (二)依赖传递
    (一)Maven基础及第一个Maven工程
  • 原文地址:https://www.cnblogs.com/pyrene/p/8094357.html
Copyright © 2020-2023  润新知