近期学了go语言的并发编程,掌握了
- 并发原语-原子锁,互斥锁,通道
- 并发原理
- 并发设计模式
今天我们就来锻炼一下,如何用学到的新知识帮助我们更好的工作,学习下面的模式需要掌握 - 通道使用
- 类型函数
- os.Signal信号
今天的模式是控制程序的执行时间,大体思路是 执行一系列类型任务队列,在执行任务队列期间,系统中断,超时中断,完成中断,都会随时打断程序的执行并返回
逻辑图如下
执行任务.png代码如下
package main
import (
"errors"
"os"
"os/signal"
"time"
)
var (
ErrTimeout = errors.New("Timeout")
ErrInterrupt = errors.New("Interrupt")
)
type RunnerFun func(int)
// @title 获取一个任务队列
// @description 获取一个任务队列
// @param d time.Duration "超时时间微妙"
// @return *Runner "任务队列结构体"
func NewRunner(d time.Duration) *Runner {
return &Runner{
timeout: time.After(d),
interrupt: make(chan os.Signal, 1),
complete: make(chan error),
}
}
type Runner struct {
tasks []RunnerFun `desc:"任务列表"`
timeout <-chan time.Time `desc:"超时通道"`
interrupt chan os.Signal `desc:"中断信号通道"`
complete chan error `desc:"完成信号通道"`
}
// @title 添加执行任务
// @description 添加执行任务到任务队列
// @param tasks ...RunnerFun "函数类型的参数"
func (r *Runner) add(tasks ...RunnerFun) {
r.tasks = append(r.tasks, tasks...)
}
func (r *Runner) start() error {
// TODO 将中断通道传至Notify函数,获取系统的信号
signal.Notify(r.interrupt, os.Interrupt)
// TODO 执行任务,并获取结果
go func() {
r.complete <- r.run()
}()
// TODO 阻塞程序,直道超时或完成
select {
case <-r.timeout:
return ErrTimeout
case <-r.complete:
return nil
}
}
// @title 执行任务
// @description 执行任务
// @return error "执行期间的错误"
func (r *Runner) run() error {
// TODO 遍历任务队列
for i, task := range r.tasks {
// TODO 无阻塞通道,当没有中断信号时,正常执行任务
select {
case <-r.interrupt:
return ErrInterrupt
default:
task(i)
}
}
return nil
}
网友评论