zoukankan      html  css  js  c++  java
  • 并行计算

    1、Goroutine协程:协程就是go提供的轻量级的独立运算过程,比线程还轻;创建一个协程,就是使用go关键字,后面跟上要运行的函数

    案例要求:1)、先计算1000以下所有能够被3整除的整数的和A

         2)、然后计算1000以下所有能够被5整除的整数和B

         3)、然后再计算1000以下所有能够被3和5整除的整数和C

         4)、使用A+B-C得到最后结果

    案例中,使用go关键字创建一个协程,协程函数内使用channel(chan数据,类似队列,在取chan中数据时,如果为空,会阻塞,直到chan中有数据)存储数据

    package main
    
    import (
        "fmt"
        "runtime"
        "time"
    )
    
    func get_sum_of_divisible(num int, divider int, resultChan chan int) {
        sum := 0
        for value := 0; value < num; value++ {
            if value%divider == 0 {
                sum += value
            }
        }
        resultChan <- sum
    }
    
    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        LIMIT := 1000
        //用于被15除结果
        job1 := make(chan int, 1)
        //用于被3,5除结果
        job2 := make(chan int, 2)
    
        t_start := time.Now()
        go get_sum_of_divisible(LIMIT, 15, job1)
        go get_sum_of_divisible(LIMIT, 3, job2)
        go get_sum_of_divisible(LIMIT, 5, job2)
    
        sum15 := <-job1
        sum3, sum5 := <-job2, <-job2
    
        sum := sum3 + sum5 - sum15
        t_end := time.Now()
        fmt.Println(sum)
        fmt.Println(t_end.Sub(t_start))
    }

    2、Channel通道:提供了协程之间的通信方式以及运行同步机制

    案例:假设训练定点投篮和三分投篮,教练在计数

    如果向channel里面写信息,必须有配对的取信息的一端;假如把下面的go count(c)注释掉,则不会有打印数据

    package main
    
    import (
        "fmt"
        "strconv"
        "time"
    )
    
    func fixed_shooting(msg_chan chan string) {
        i := 1
        for {
            msg_chan <- "fixed shooting"
            var str string = strconv.Itoa(i)
            fmt.Println("continue fixed shooting..." + str)
            i++
        }
    }
    
    func count(msg_chan chan string) {
        for {
            msg := <-msg_chan
            fmt.Println(msg)
            time.Sleep(time.Second * 1)
        }
    }
    
    func main() {
        var c chan string
        c = make(chan string)
    
        go fixed_shooting(c)
        go count(c)
    
        var input string
        fmt.Scanln(&input)
    }

    加一个三分投篮方法,可以看出,写入channel中的数据,必须读取出来才能再次写入,如果没有读取出来,再次写入会失败

    package main
    
    import (
        "fmt"
        "strconv"
        "time"
    )
    
    func three_point_shooting(msg_chan chan string) {
        i := 1
        for {
            var str string = strconv.Itoa(i)
            msg_chan <- "three point shooting--" + str
            i++
        }
    }
    
    func fixed_shooting(msg_chan chan string) {
        i := 1
        for {
            var str string = strconv.Itoa(i)
            msg_chan <- "fixed shooting--" + str
            i++
        }
    }
    
    func count(msg_chan chan string) {
        for {
            msg := <-msg_chan
            fmt.Println(msg)
            time.Sleep(time.Second * 1)
        }
    }
    
    func main() {
        var c chan string
        c = make(chan string)
    
        go fixed_shooting(c)
        go three_point_shooting(c)
        go count(c)
    
        var input string
        fmt.Scanln(&input)
    }

    结果图如下,结果是交替输出的,也就是channel中输入的必须输出后才能再次输入

    3、Channel通道方向

    var c chan string  可读写channel,可写入也可读取

    var c chan<- string  只写channel,只能写入

    var c <-chan string  只读channel,只能读取

    4、多通道(Select)

    案例中,select依次检查每个channel是否有消息传递过来,如果有就输出;如果同时有多个消息到达,select随机选择一个channel来从中读取消息;如果没有一个channel有消息到达,那么select语句就阻塞在这里一直等待。select 语句也可以有default片段,case不符合时会执行default语句片段。select中case、default类似switch中case、default

    下面case中使用了time.After,可以这样理解,main函数也是一个channel,time.After让main阻塞指定时间后,读出时间消息(案例中没有用变量存储返回的时间)

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func fixed_shooting(msg_chan chan string) {
        var times = 3
        var t = 1
        for {
            if t <= times {
                msg_chan <- "fixed shooting"
            }
            t++
            time.Sleep(time.Second * 1)
        }
    }
    
    func three_point_shooting(msg_chan chan string) {
        var times = 3
        var t = 1
        for {
            if t <= times {
                msg_chan <- "three point shooting"
            }
            t++
            time.Sleep(time.Second * 1)
        }
    }
    
    func main() {
        c_fixed := make(chan string)
        c_3_point := make(chan string)
    
        go fixed_shooting(c_fixed)
        go three_point_shooting(c_3_point)
    
        go func() {
            for {
                select {
                case msg1 := <-c_fixed:
                    fmt.Println(msg1)
                case msg2 := <-c_3_point:
                    fmt.Println(msg2)
                case <-time.After(time.Second * 5):
                    fmt.Println("timeout check again...")
                }
            }
        }()
    
        var input string
        fmt.Scanln(&input)
    }

    结果图

    5、Channel Buffer通道缓冲区:一般我们定义的channel都是同步的,也就是说接受端和发送端彼此等待对方OK才开始。但是如果执行了channel缓冲区大小,那么消息的发送和接收是异步的,除非channel缓冲区已经满了

    package main
    
    import (
        "fmt"
        "strconv"
        "time"
    )
    
    func shooting(msg_chan chan string) {
        var group = 1
        for {
            for i := 1; i <= 10; i++ {
                msg_chan <- strconv.Itoa(group) + ":" + strconv.Itoa(i)
            }
            group++
            time.Sleep(time.Second * 5)
        }
    }
    
    func count(msg_chan chan string) {
        for {
            fmt.Println(<-msg_chan)
        }
    }
    
    func main() {
        var c = make(chan string, 20)
        go shooting(c)
        go count(c)
        var input string
        fmt.Scanln(&input)
    }
  • 相关阅读:
    LeetCode 123. Best Time to Buy and Sell Stock III (stock problem)
    精帖转载(关于stock problem)
    LeetCode 122. Best Time to Buy and Sell Stock II (stock problem)
    LeetCode 121. Best Time to Buy and Sell Stock (stock problem)
    LeetCode 120. Triangle
    基于docker 搭建Elasticsearch5.6.4 分布式集群
    从零开始构建一个centos+jdk7+tomcat7的docker镜像文件
    Harbor实现容器镜像仓库的管理和运维
    docker中制作自己的JDK+tomcat镜像
    docker镜像制作---jdk7+tomcat7基础镜像
  • 原文地址:https://www.cnblogs.com/hujiapeng/p/9651701.html
Copyright © 2011-2022 走看看