go并发编程 - 待完善

2020-08-25  本文已影响0人  如逆水行舟不进则退

package main

import (
  "fmt"
  "time"
)

func main() {
  //fmt.Println("Hello World")
  go printNum()
  go printLetter()
  time.Sleep(3 * time.Second)
  fmt.Println("\n main over ... ")
}

func printNum() {
  for i:=1;i<=5;i++ {
    time.Sleep(250 * time.Millisecond)
    fmt.Printf("%d", i)
  }
}

func printLetter() {
  for i:='a';i<='e';i++ {
    time.Sleep(400 * time.Millisecond)
    fmt.Printf("%c", i)
  }
}
package main

func main() {
  //fmt.Println("Hello World")
  var ch0 chan string
  ch1 := make(chan string)
  ch2 := make(chan interface{})
  type Equip struct {}
  ch3 := make(chan *Equip)
}

package main

import "fmt"

func main() {
  //fmt.Println("Hello World")
  ch1 := make(chan string)
  go sendData(ch1)
  // 1.循环接受数据方式1
  //for {
  //  data := <-ch1
  //  if data == "" {
  //    break
  //  }
  //  fmt.Println("从通道数据中读取数据方式1:", data)
  //}

  // 2.循环接受数据方式2
  //for {
  //  data, ok := <- ch1
  //  fmt.Println(ok)
  //  if !ok {
  //    break
  //  }
  //  fmt.Println("从通道数据中读取数据方式2:", data)
  //}

  // 3.循环接收数据方式3
  // for ... range 循环会自动判断通道是否关闭,自动break循环
  for value := range ch1 {
    fmt.Println("从通道数据中读取数据方式3:", value)
  }

}

func sendData(ch1 chan string) {
  defer close(ch1)
  for i := 0; i < 3; i++ {
    ch1 <- fmt.Sprintf("发送数据 %d\n", i)
  }
  fmt.Println("发送数据完毕。。")
  // 显式调用close() 实现关闭通道
}

package main

import (
  "fmt"
  "time"
)

func main() {
  //fmt.Println("Hello World")
  var ch1 chan int
  ch1 = make(chan int)
  fmt.Printf("%T \n", ch1)
  ch2 := make(chan bool)
  go func() {
    data, ok := <-ch1
    if ok {
      fmt.Println("子goroutine 取到数值:", data)
    }
    time.Sleep(1 * time.Second)
    fmt.Println("子goroutine over ...")
    ch2 <- true
  }()
  ch1 <- 10
  <-ch2 // 阻塞
  fmt.Println("main over ...")
}


package main

import "fmt"

func main() {
  //fmt.Println("Hello World")
  var ch1 chan int
  ch1 = make(chan int)
  go func() {
    ch1 <- 100
    ch1 <- 100
    close(ch1)
    //ch1 <- 10 // 关闭channel, 无法写入数据
  }()
  data, ok := <-ch1
  fmt.Println("main 读取数据:", data, ok)
  data, ok = <-ch1
  fmt.Println("main 读取数据:", data, ok)
  data, ok = <-ch1
  fmt.Println("main 读取数据:", data, ok)
  data, ok = <-ch1
  fmt.Println("main 读取数据:", data, ok)
  data, ok = <-ch1
  fmt.Println("main 读取数据:", data, ok)
}

输出:
main 读取数据: 100 true
main 读取数据: 100 true
main 读取数据: 0 false
main 读取数据: 0 false
main 读取数据: 0 false

package main

import (
  "fmt"
  "time"
)

func main() {
  //fmt.Println("Hello World")
  //1.非缓冲通道
  ch1 := make(chan int)
  fmt.Println("非缓冲通道", len(ch1), cap(ch1))
  go func() {
   data := <- ch1
   fmt.Println("获得数据", data)
  }()
  ch1 <- 100
  time.Sleep(time.Second)
  fmt.Println("赋值ok","main over...")

  //2.非缓冲通道
  ch2 := make(chan string)
  go sendData(ch2)
  time.Sleep(time.Second)
  for data := range ch2 {
    time.Sleep(time.Second)
    fmt.Println("\t 读取数据:", data)
  }
  fmt.Println("main over ...")

  // 缓冲通道,缓冲区满了才会阻塞
  ch3 := make(chan string, 6)
  go sendData(ch3)
  for data := range ch3 {
   fmt.Println("\t 读取数据:", data)
  }
  fmt.Println("main over")
}

func sendData(ch chan string) {
  for i := 1; i <=3; i++ {
    ch <- fmt.Sprintf("data %d", i)
    fmt.Println("往通道放入数据:", i)
  }
  defer close(ch)
}

package main

import (
  "fmt"
  "math/rand"
  "strings"
  "time"
)

func main() {
  //fmt.Println("Hello World")
  // 用channel来传递数据,不再需要自己去加锁维护一个全局的阻塞队列
  ch1 := make(chan int)
  ch_bool1 := make(chan bool) // 判断结束
  ch_bool2 := make(chan bool) // 判断结束
  ch_bool3 := make(chan bool) // 判断结束

  rand.Seed(time.Now().UnixNano())

  // 生产者
  go producer(ch1)
  // 消费者
  go consumer(1, ch1, ch_bool1)
  go consumer(2, ch1, ch_bool2)
  go consumer(3, ch1, ch_bool3)

  <-ch_bool1
  <-ch_bool2
  <-ch_bool3

  defer fmt.Println("main...over...")

  fmt.Println("main over")
}

func producer(ch1 chan int) {
  for i := 1; i <= 10; i++ {
    ch1 <- i
    fmt.Println("生产蛋糕,编号:", i)
    time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)
  }
  defer close(ch1)
}

func consumer(num int, ch1 chan int, ch chan bool) {
  for data := range ch1 {
    pre := strings.Repeat("——————", num)
    fmt.Printf("%s %d 号购买 %d号蛋糕 \n", pre, num, data)
    time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)
  }
  ch <- true
  defer close(ch)
}



package main

import (
  "fmt"
  "time"
)

func main() {
  // 双向通道
  ch1 := make(chan string)
  go fun1(ch1)

  data := <-ch1

  fmt.Println("main,接受到数据:", data)
  ch1 <- "Go语言好学吗?"
  ch1 <- "Go语言好学吗???"
  go fun2(ch1)
  go fun3(ch1)
  time.Sleep(time.Second)

  fmt.Println("main over")
}

func fun1(ch1 chan string) {
  ch1 <- "我是Steven老师"
  data := <-ch1
  data2 := <-ch1
  fmt.Println("回应:", data, data2)
}

// 功能:只有写入数据
func fun2(ch1 chan<- string) {
  // 只能写入
  ch1 <- "How are you?"
}

func fun3(ch1 <-chan string) {
  data := <-ch1
  fmt.Println("只读:", data)
}


package main

import (
  "fmt"
  "time"
)

func main() {

  // 创建计时器
  timer1 := time.NewTimer(5 * time.Second)
  // fmt.Printf("%T \n", timer1)
  fmt.Println(time.Now())
  data := <- timer1.C // <-chan time.Time
  fmt.Printf("%T \n", timer1.C)
  fmt.Printf("%T \n", data)
  fmt.Println(data)
}
package main

import (
  "fmt"
  "time"
)

func main() {

  // 2.使用After(), 返回值 <-chan Time , 同Timer.C
  ch1 := time.After(5 * time.Second)
  fmt.Println(time.Now())
  data := <-ch1
  fmt.Printf("%T \n", data)
  fmt.Println(data)
}
package main

import (
  "fmt"
)

func main() {

  ch1 := make(chan int)
  ch2 := make(chan int)
  go func() {
    ch1 <- 100
  }()

  go func() {
    ch2 <- 200
  }()

  // time.Sleep(time.Second)
  select {
  case data := <-ch1:
      fmt.Println("ch1中读取数据了:", data)
  case data := <-ch2:
      fmt.Println("ch2中读取数据了:", data)
  default:
      fmt.Println("执行了default...")
  }
}


package main

import (
  "fmt"
  "time"
)

func main() {

  ch1 := make(chan int)
  ch2 := make(chan int)

  go func() {
    time.Sleep(10 * time.Millisecond)
    data := <-ch1
    fmt.Println("ch1:", data)
  }()

  go func() {
    time.Sleep(2 * time.Second)
    data := <-ch2
    fmt.Println("ch2:", data)
  }()

  select {
  case ch1 <- 100 :// 阻塞
      close(ch1)
      fmt.Println("ch1 中写入数据")
  case ch2 <- 200: // 阻塞
      close(ch2)
      fmt.Println("ch2 中写入数据")
  case <-time.After(2 * time.Millisecond) : // 阻塞
      fmt.Println("执行延时通道")
  //default:
  //  fmt.Println("default...")
  }

  time.Sleep( 4 * time.Second)
  fmt.Printf("main over")
}


package main

import (
  "fmt"
  "math/rand"
  "strings"
  "sync"
  "time"
)

func main() {
  var wg sync.WaitGroup
  fmt.Printf("%T \n", wg) // sync.WaitGroup
  fmt.Println(wg)
  wg.Add(3)
  rand.Seed(time.Now().UnixNano())

  go printNum(&wg, 1)
  go printNum(&wg, 2)
  go printNum(&wg, 3)

  wg.Wait() // 进入阻塞状态,当计数为0时解除阻塞
  defer fmt.Println("main over ...")

}

func printNum(wg *sync.WaitGroup, num int) {
  for i := 1; i <=3; i++ {
    // 在每个Goroutine 前面添加多个制表符方便观看打印结果
    pre := strings.Repeat("\t", num-1)
    fmt.Printf("%s 第 %d号子goroutine, %d \n", pre, num, i)
    time.Sleep(time.Second)
  }
  wg.Done() // 计数器减1
}

package main

import (
  "fmt"
  "strconv"
  "strings"
  "sync"
  "time"
)
var tickets int = 20
var wg sync.WaitGroup
var mutex sync.Mutex

func main() {
  wg.Add(4)
  go saleTickets("1号窗口", &wg)
  go saleTickets("2号窗口", &wg)
  go saleTickets("3号窗口", &wg)
  go saleTickets("4号窗口", &wg)
  wg.Wait()
  defer fmt.Println("所有车票都售空")
}

func saleTickets(name string, wg *sync.WaitGroup) {
  defer wg.Done()
  for {
    // 锁定
    mutex.Lock()
    if tickets > 0 {
      time.Sleep(1 * time.Second)
      // 获取窗口的编号
      num, _ := strconv.Atoi(name[:1])
      pre := strings.Repeat("------", num)
      fmt.Println(pre, name, tickets)
      tickets--
    } else {
      fmt.Printf("%s 结束售票 \n", name)
      mutex.Unlock()
      break
    }
    // 解锁
    mutex.Unlock()
  }
}


上一篇 下一篇

猜你喜欢

热点阅读