GO并发编程综合应用

一.GO并发编程综合应用

1.生产者消费者模式
1.1需求分析

​ 生产者每秒生产一个商品,并通过物流公司取货

​ 物流公司将商品运输到商铺

​ 消费者阻塞等待商铺到货,需要消费10次商品

1.2实现原理

GO并发编程综合应用_第1张图片

1.3代码实现:
package main

import (
   "fmt"
   "strconv"
   "time"
)

func main() {
   storageChan := make(chan Product, 10)
   shopChan := make(chan Product, 10)
   exitChan := make(chan bool, 1)
   for i := 1; i < 9; i++ {
      go Producer(storageChan, 10)
   }

   go Logistics(storageChan, shopChan)
   go Consumer(shopChan, 10, exitChan)
   if <-exitChan {
      return
   }
}

// Product 商品
type Product struct {
   Name string
}

// Producer 生产者
func Producer(storageChan chan<- Product, count int) {
   for {
      producer := Product{"商品:" + strconv.Itoa(count)}
      storageChan <- producer
      count--
      time.Sleep(time.Second)
      fmt.Println("生产了", producer)
      if count < 1 {
         return
      }
   }
}

// Logistics 物流公司
func Logistics(storageChan <-chan Product, shopChan chan<- Product) {
   for {
      product := <-storageChan
      shopChan <- product
      fmt.Println("运输了", product)
   }
}

// Consumer 消费者
func Consumer(shopChan <-chan Product, count int, exitChan chan<- bool) {
   for {
      product := <-shopChan
      fmt.Println("消费了", product)
      count--
      if count < 1 {
         exitChan <- true
         return
      }
   }
}
2.协程管道定时任务的应用
2.1需求分析

​ 1.定时执行某个任务,类似延时消息队列

​ 2.或者周期性的执行某个任务,类似定期同步某些数据

2.2实现原理

GO并发编程综合应用_第2张图片

2.3代码实现:
package main

import (
   "fmt"
   "time"
)

func main() {
   //方式1:
   fmt.Println("当前时间:", time.Now())
   //timer := time.NewTimer(time.Second * 3)
   //t := <-timer.C //timer.C一个只读的管道

   //fmt.Println(t)

   //方式二:
   t := <-time.After(time.Second * 3) //源码可见,实际上NewTimer(d).C
   fmt.Println(t)
}
3.定时器的终止与重置

​ NewTimer, Stop, Reset

package main

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

var flag bool = isStopTimer()

func main() {
	//方式1:
	fmt.Println("当前时间:", time.Now())
	timer := time.NewTimer(time.Second * 3)

	if flag {
		timer.Stop() //如果停止了timer,还去拿fatal error: all goroutines are asleep - deadlock!
	} else {
		t := <-timer.C //timer.C一个只读的管道
		fmt.Println(t)
	}
	
}

func isStopTimer() bool {
	rand.Seed(time.Now().UnixNano())
	tempInt := rand.Intn(2) + 18
	if tempInt >= 18 {
		fmt.Println("已经找到了大于18,结束timer")
		return true
	} else {
		return false
	}
}

func isResetTimer() int {
	rand.Seed(time.Now().UnixNano())
	tempInt := rand.Intn(4) + 19
	fmt.Println("已经找到",tempInt)
	return tempInt-18
}
4.需要每隔时间触发任务
4.1实现原理:

GO并发编程综合应用_第3张图片

4.2代码实现
package main

import (
   "fmt"
   "time"
)

func main() {
   var count int = 0
   ticker := time.NewTimer(time.Second * 1)
   go func() {
      for {
         t := <-ticker.C
         fmt.Println("时间:", t.Format("2006-01-02 03:04:05PM"))
         count++
         if count > 2 {
            ticker.Stop()
         }
      }
   }()
   time.Sleep(time.Second * 10)
   fmt.Println("游戏结束")
}
4.3改造成任务队列
package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   var count int = 0
   var wg sync.WaitGroup
   wg.Add(1)
   ticker := time.NewTicker(time.Second * 1)
   go func() {
      defer wg.Done()
      defer ticker.Stop()
      for {
         t := <-ticker.C
         fmt.Println("时间:", t.Format("2006-01-02 03:04:05PM"))
         count++
         if count > 2 {
            return
         }
      }
   }()
   wg.Wait()
   fmt.Println("游戏结束")
}

你可能感兴趣的:(GO语言,golang,开发语言,后端)