golang select chan实现任务优先级编排!!!

w570955342 · · 1728 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

### 前提: **1.job1优先级高于job2** **2.job1和job2均需要1秒的执行时间** **3.每500毫秒启动3个job2,每2秒启动1个job1** ### 结论: **无论有多少job2,只要来了job1,就会优先执行job1** ```go package main import ( "context" "log" "os" "os/signal" "syscall" "time" ) func main() { // 定义1个阻塞主go程管道 ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) // 定义2个job分发管道 ch1, ch2 := make(chan string), make(chan string) job1 := "执行job1" job2 := "执行job2" // 模拟超时,ctx超时后停止启动任务和执行任务 ctx, _ := context.WithTimeout(context.Background(), time.Second*10) // 启动worker函数,执行管道ch1和ch2收到的任务 go worker(ch1, ch2, ctx) // 定义2个启动任务的周期定时器 tiker1, tiker2 := time.NewTicker(time.Second*2), time.NewTicker(time.Millisecond*500) // 每隔500毫秒启动3个job2 go func() { for { select { case <-tiker2.C: log.Println("启动3个job2...") for i := 0; i < 3; i++ { go func() { ch2 <- job2 }() } case <-ctx.Done(): log.Println("收到结束信号,停止启动job2!") return } } }() // 每隔2秒启动1个job1 loop: for { select { case <-ctx.Done(): log.Println("收到结束信号,停止启动job1!") break loop case <-tiker1.C: log.Println("启动1个job1...") go func() { ch1 <- job1 }() } } // 等待关闭信号 select { case sig := <-ch: log.Println("收到关闭信号:", sig) } log.Println("finish!") } // 按优先级处理任务函数 func worker(ch1, ch2 <-chan string, ctx context.Context) { defer log.Println("defer close worker") for { // 第一个select如果先收到job1,则直接执行job1 select { case <-ctx.Done(): log.Println("收到结束信号,退出worker函数!") return case job1 := <-ch1: // 模拟job1需要1秒执行结束 log.Println(job1) time.Sleep(time.Second) case job2 := <-ch2: // 第一个select如果先收到job2,则进入第2个select // 判断此时是否存在未执行的job1,如果job1存在,则执行job1;如果job1不存在,则执行job2 priority: for { select { case <-ctx.Done(): log.Println("执行job2被插队: 收到结束信号,退出worker函数!") return case job1 := <-ch1: // 模拟job1需要1秒执行结束 log.Println("执行job2被插队:", job1) time.Sleep(time.Second) default: break priority } } // 模拟job2需要1秒执行结束 log.Println("此时没有job1:", job2) time.Sleep(time.Second) } } } ``` #### 日志: ``` go 2020/12/11 23:32:11 启动3个job2... 2020/12/11 23:32:11 此时没有job1: 执行job2 2020/12/11 23:32:12 启动3个job2... 2020/12/11 23:32:12 启动3个job2... 2020/12/11 23:32:12 此时没有job1: 执行job2 2020/12/11 23:32:13 启动1个job1... 2020/12/11 23:32:13 启动3个job2... 2020/12/11 23:32:13 启动3个job2... 2020/12/11 23:32:13 执行job2被插队: 执行job1 2020/12/11 23:32:14 启动3个job2... 2020/12/11 23:32:14 启动3个job2... 2020/12/11 23:32:14 此时没有job1: 执行job2 2020/12/11 23:32:15 启动1个job1... 2020/12/11 23:32:15 启动3个job2... 2020/12/11 23:32:15 启动3个job2... 2020/12/11 23:32:15 执行job2被插队: 执行job1 2020/12/11 23:32:16 启动3个job2... 2020/12/11 23:32:16 启动3个job2... 2020/12/11 23:32:16 此时没有job1: 执行job2 2020/12/11 23:32:17 启动1个job1... 2020/12/11 23:32:17 启动3个job2... 2020/12/11 23:32:17 启动3个job2... 2020/12/11 23:32:17 执行job2被插队: 执行job1 2020/12/11 23:32:18 启动3个job2... 2020/12/11 23:32:18 启动3个job2... 2020/12/11 23:32:18 此时没有job1: 执行job2 2020/12/11 23:32:19 启动1个job1... 2020/12/11 23:32:19 启动3个job2... 2020/12/11 23:32:19 启动3个job2... 2020/12/11 23:32:19 执行job2被插队: 执行job1 2020/12/11 23:32:20 启动3个job2... 2020/12/11 23:32:20 启动3个job2... 2020/12/11 23:32:20 此时没有job1: 执行job2 2020/12/11 23:32:21 启动1个job1... 2020/12/11 23:32:21 启动3个job2... 2020/12/11 23:32:21 收到结束信号,停止启动job1! 2020/12/11 23:32:21 收到结束信号,停止启动job2! 2020/12/11 23:32:21 收到结束信号,退出worker函数! 2020/12/11 23:32:21 defer close worker 2020/12/11 23:32:23 收到关闭信号: interrupt 2020/12/11 23:32:23 finish! ```

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1728 次点击  
加入收藏 微博
5 回复  |  直到 2020-12-15 14:37:59
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传