zoukankan      html  css  js  c++  java
  • goroutine channel

     

     

    package main
    import (
        "fmt"
        _ "time"
        "sync"
    )
    
    // 需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到map中。
    // 最后显示出来。要求使用goroutine完成 
    
    // 思路
    // 1. 编写一个函数,来计算各个数的阶乘,并放入到 map中.
    // 2. 我们启动的协程多个,统计的将结果放入到 map中
    // 3. map 应该做出一个全局的.
    
    var (
        myMap = make(map[int]int, 10)  
        //声明一个全局的互斥锁
        //lock 是一个全局的互斥锁, 
        //sync 是包: synchornized 同步
        //Mutex : 是互斥
        lock sync.Mutex
    )
    
    
    //使用协程+管道  ===>???
    
    // test 函数就是计算 n!, 让将这个结果放入到 myMap
    func test(n int) {
        
        res := 1
        for i := 1; i <= n; i++ {
            res *= i
        }
    
        //这里我们将 res 放入到myMap
        //加锁
        lock.Lock()
        myMap[n] = res //concurrent map writes?
        //解锁
        lock.Unlock()
    }
    
    func main() {
    
        // 我们这里开启多个协程完成这个任务[200个]
        for i := 1; i <= 20; i++ {
            go test(i)
        }
    
    
        //休眠10秒钟【第二个问题 】
        //time.Sleep(time.Second * 5)
    
        //这里我们输出结果,变量这个结果
        lock.Lock()
        for i, v := range myMap {
            fmt.Printf("map[%d]=%d
    ", i, v)
        }
        lock.Unlock()
    
    }

    package main
    import (
        "fmt"
    )
    
    func main() {
    
        //演示一下管道的使用
        //1. 创建一个可以存放3个int类型的管道
        var intChan chan int
        intChan = make(chan int, 3)
    
        //2. 看看intChan是什么
        fmt.Printf("intChan 的值=%v intChan本身的地址=%p
    ", intChan, &intChan)
    
    
        //3. 向管道写入数据
        intChan<- 10
        num := 211
        intChan<- num
        intChan<- 50
        // //如果从channel取出数据后,可以继续放入
        <-intChan
        intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量
    
    
        //4. 看看管道的长度和cap(容量)
        fmt.Printf("channel len= %v cap=%v 
    ", len(intChan), cap(intChan)) // 3, 3
    
        //5. 从管道中读取数据
    
        var num2 int
        num2 = <-intChan 
        fmt.Println("num2=", num2)
        fmt.Printf("channel len= %v cap=%v 
    ", len(intChan), cap(intChan))  // 2, 3
    
        //6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock
    
        num3 := <-intChan
        num4 := <-intChan
    
        //num5 := <-intChan
    
        fmt.Println("num3=", num3, "num4=", num4/*, "num5=", num5*/)
    
    }
    intChan 的值=0xc000086080 intChan本身的地址=0xc000080018
    channel len= 3 cap=3 
    num2= 211
    channel len= 2 cap=3 
    num3= 50 num4= 98
    

      

    package main
    
    import "fmt"
    
    func main()  {
        var mapchan chan map[string]string
        mapchan = make(chan map[string]string,10)
    
        m1 := make(map[string]string,10)
        m1["name"] = "阿凡达"
        m1["age"] = "25"
        m2 := make(map[string]string,10)
        m2["name"] = "欧阳"
        m2["age"] = "28"
        mapchan <- m1
        mapchan <- m2
        fmt.Println(mapchan)
    }

    package main
    
    import "fmt"
    
    func main()  {
        intchan := make(chan int ,3)
        intchan <- 100
        intchan <- 200
        close(intchan)
        fmt.Println("11111111111")
        n1 :=  <-intchan
        fmt.Println(n1) //100
        fmt.Println(<-intchan) //200
        fmt.Println(<-intchan) //0
        fmt.Println(<-intchan) //0
        intchan <- 300 //panic: send on closed channel
    }

    package main
    import (
        "fmt"
        "time"
    )
    
    
    //write Data
    func writeData(intChan chan int) {
        for i := 1; i <= 50; i++ {
            //放入数据
            intChan<- i //
            fmt.Println("writeData ", i)
            //time.Sleep(time.Second)
        }
        close(intChan) //关闭
    }
    
    //read data
    func readData(intChan chan int, exitChan chan bool) {
    
        for {
            v, ok := <-intChan
            if !ok {
                break
            }
            time.Sleep(time.Second)
            fmt.Printf("readData 读到数据=%v
    ", v) 
        }
        //readData 读取完数据后,即任务完成
        exitChan<- true
        close(exitChan)
    
    }
    
    func main() {
    
        //创建两个管道
        intChan := make(chan int, 10)
        exitChan := make(chan bool, 1)
        
        go writeData(intChan)
        go readData(intChan, exitChan)
    
        //time.Sleep(time.Second * 10)
        for {
            _, ok := <-exitChan
            if !ok {
                break
            }
        }
    
    }
    View Code

     

    package main
    import (
        "fmt"
        "time"
    )
    
    
    
    //向 intChan放入 1-8000个数
    func putNum(intChan chan int) {
    
        for i := 1; i <= 80000; i++ {    
            intChan<- i
        }
    
        //关闭intChan
        close(intChan)
    }
    
    // 从 intChan取出数据,并判断是否为素数,如果是,就
    //     //放入到primeChan
    func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
    
        //使用for 循环
        // var num int
        var flag bool // 
        for {
            //time.Sleep(time.Millisecond * 10)
            num, ok := <-intChan //intChan 取不到..
            
            if !ok { 
                break
            }
            flag = true //假设是素数
            //判断num是不是素数
            for i := 2; i < num; i++ {
                if num % i == 0 {//说明该num不是素数
                    flag = false
                    break
                }
            }
    
            if flag {
                //将这个数就放入到primeChan
                primeChan<- num
            }
        }
    
        fmt.Println("有一个primeNum 协程因为取不到数据,退出")
        //这里我们还不能关闭 primeChan
        //向 exitChan 写入true
        exitChan<- true    
    
    }
    
    func main() {
    
        intChan := make(chan int , 1000)
        primeChan := make(chan int, 20000)//放入结果
        //标识退出的管道
        exitChan := make(chan bool, 8) // 4个
    
    
    
        start := time.Now().Unix()
        
        //开启一个协程,向 intChan放入 1-8000个数
        go putNum(intChan)
        //开启4个协程,从 intChan取出数据,并判断是否为素数,如果是,就
        //放入到primeChan
        for i := 0; i < 8; i++ {
            go primeNum(intChan, primeChan, exitChan)
        }
    
        //这里我们主线程,进行处理
        //直接
        go func(){
            for i := 0; i < 8; i++ {
                <-exitChan
            }
    
            end := time.Now().Unix()
            fmt.Println("使用协程耗时=", end - start)
    
            //当我们从exitChan 取出了4个结果,就可以放心的关闭 prprimeChan
            close(primeChan)
        }()
    
    
        //遍历我们的 primeChan ,把结果取出
        for {
            _, ok := <-primeChan
            if !ok{
                break
            }
            //将结果输出
            //fmt.Printf("素数=%d
    ", res)
        }
    
        fmt.Println("main线程退出")
    
    
        
    }
    View Code

     

       

    package main
    
    import "fmt"
    func send(ch chan<- int,exitchan chan struct{}){
        for i :=0 ; i<10 ;i++{
            ch<- i
        }
        close(ch)
        var a struct{}
        exitchan<- a
    }
    func recv(ch <-chan int,exitchan chan struct{}){
        for{
            v,ok:= <-ch
            if !ok{
                break
            }
            fmt.Println(v)
        }
        var a struct{}
        exitchan<- a
    }
    
    
    
    func main()  {
        var ch chan int
        ch = make(chan int,10)
        exitchan := make(chan struct{},2)
    
        go send(ch,exitchan)
        go recv(ch,exitchan)
    
        //var total = 0
        //for _ = range exitchan{
        //    total++
        //    if total ==2{
        //        break
        //    }
        //}
        var total = 0
        for{
            _,ok:= <-exitchan
            if !ok{
                break
            }
            total++
            if total ==2{
                break
            }
        }
        fmt.Println("结束")
    
    }
    View Code

     

    package main
    
    import "fmt"
    
    
    func main()  {
    
        intchan := make(chan int,10)
        for i := 0;i<10;i++{
            intchan <- i
        }
    
        stringchan := make(chan string ,5)
    
        for i:=0;i<5;i++{
            stringchan<- "hello"+fmt.Sprintf("%d",i)
        }
    
        for{
            select{
                case v:= <-intchan:
                    fmt.Printf("从intchan读取的数据%d
    ",v)
                case v := <-stringchan:
                    fmt.Printf("从stringchan读取的数据%d
    ",v)
            default:
                fmt.Printf("都取不到了,不玩了")
                return
            }
        }
    }
    View Code

    package main
    
    import (
        "time"
        "fmt"
    )
    
    func sayHello(){
        for i:=0;i<10;i++{
            //time.Sleep(time.Second)
            fmt.Println("hello world")
        }
    }
    
    func test(){
        defer func(){
            if err := recover();err!=nil{
                fmt.Println("test() 发生错误",err)
            }
        }()
        var myMap map[int]string
        //myMap = make(map[int]string,6)
        myMap[0] = "golang"
    }
    
    
    func main()  {
      go sayHello()
      go test()
    
      time.Sleep(time.Second*10)
    
    }
    GOROOT=D:go #gosetup
    GOPATH=null #gosetup
    D:goingo.exe build -i -o C:UsersAdministratorAppDataLocalTemp\___go_build_03_go.exe D:/gospace/03.go #gosetup
    D:softGoLandin
    unnerw.exe C:UsersAdministratorAppDataLocalTemp\___go_build_03_go.exe #gosetup
    hello world
    hello world
    hello world
    hello world
    hello world
    hello world
    hello world
    hello world
    hello world
    hello world
    test() 发生错误 assignment to entry in nil map

     sync:

     

     sync案例

    上图每次执行结果都不相同

    通过加互斥锁

  • 相关阅读:
    Sqlite教程(1) SQLiteOpenHelper
    检查网络连接状态。
    GSON解译Json为DTO
    Okhttp教程 (1)
    HashMap的扩容算法
    回溯算法
    动态规划
    实现自旋锁
    Java堆
    垃圾回收算法总结
  • 原文地址:https://www.cnblogs.com/sunlong88/p/11203892.html
Copyright © 2011-2022 走看看