Go基础编程实践(七)—— 并发

同时运行多个函数

观察常规代码和并发代码的输出顺序。

// 常规代码,顺序执行,依次输出
package main

import (
    "fmt"
    "time"
)

func main() {
    strN := []string{"a", "b", "c", "d"}
    for _, strV := range strN {
        time.Sleep(time.Second)
        fmt.Println(strV)
    }

    intN := []int{1, 2, 3, 4}
    for _, intV := range intN {
        time.Sleep(time.Second)
        fmt.Println(intV)
    }
}
// 并发代码,并发执行,无序输出
package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        strN := []string{"a", "b", "c", "d"}
        for _, strV := range strN {
            time.Sleep(time.Second)
            fmt.Println(strV)
        }
    }()

    go func() {
        intN := []int{1, 2, 3, 4}
        for _, intV := range intN {
            time.Sleep(time.Second)
            fmt.Println(intV)
        }
    }()

    // 防止main routine过早退出
    time.Sleep(10 * time.Second)
}

通道的关闭

// 生产者关闭通道
package main

import (
    "time"
    "fmt"
)

func main() {
    channel := make(chan string)
    go func() {
        names := []string{"Jack", "Mike", "John", "Kitty"}

        for _, name := range names {
            time.Sleep(time.Second)
            // fmt.Println(name)
            channel <- name
        }
        // 发送完毕关闭通道,否则引起死锁
        close(channel)
    }()

    for data := range channel {
        fmt.Println(data)
    }
}

在通道中传递数据

// 利用无缓冲通道同步传递数据
package main

import "fmt"

func main(){
  nameChannel := make(chan string)
  done := make(chan string)

  go func(){
    names := []string {"tarik", "michael", "gopi", "jessica"}
    for _, name := range names {
      fmt.Println("Processing the first stage of: " + name)
      nameChannel <- name
    }
    close(nameChannel)
  }()

  go func(){
    for name := range nameChannel{
      fmt.Println("Processing the second stage of: " + name)
    }
    done <- ""
  }()

  <-done
}
// 利用有缓冲通道传递数据,提高性能
package main

import "fmt"

func main(){
  nameChannel := make(chan string, 5)
  done := make(chan string)

  go func(){
    names := []string {"tarik", "michael", "gopi", "jessica"}
    for _, name := range names {
      fmt.Println("Processing the first stage of: " + name)
      nameChannel <- name
    }
    close(nameChannel)
  }()

  go func(){
    for name := range nameChannel{
      fmt.Println("Processing the second stage of: " + name)
    }
    done <- ""
  }()

  <-done
}

并发等待

package main
import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        // 遍历一次,增加一次计数
        wg.Add(1)
        go func(){
            fmt.Println("Hello World")
            // 执行一次,减少一次计数
            wg.Done()
        }()
    }
    // 等待计数归零,结束程序
    wg.Wait()
}
// 利用通道等待
package main

import (
    "time"
    "fmt"
)

func main() {
    channel := make(chan string)
    go func() {
        names := []string{"Jack", "Mike", "John", "Kitty"}

        for _, name := range names {
            time.Sleep(time.Second)
            fmt.Println(name)
            // channel <- name
        }
        // 遍历完毕向通道发送数据,告诉main routine已执行完毕
        channel <- ""
    }()
    // main routine收到数据,退出程序
    // 因为只是为了同步,不需要通道中的数据,所以将数据抛弃
    <-channel
}

选择并发结果

package main

import (
    "time"
    "fmt"
)

func main() {
    channel1 := make(chan string)
    channel2 := make(chan string)
  
    go func(){
        time.Sleep(1*time.Second)
        channel1 <- "Hello from channel1"
    }()
    go func(){
        time.Sleep(1 * time.Second)
        channel2 <- "Hello from channel2"
    }()
    var result string
    // select随机选择满足条件的case
    select {
    case result = <-channel1:
        fmt.Println(result)
    case result = <-channel2:
        fmt.Println(result)
    }
}

posted on 2019-07-07 20:23  GaiheiluKamei  阅读(364)  评论(0编辑  收藏  举报

导航