并发模型,runner

并发模型,runner

runner

模型概述

​ runner模型做的事情就是,我们把任务丢给一个runner,然后runner去帮我们在后台跑这些任务,如果执行任务的过程超时或者收到了中断,我们就报错。

runner的定义

这里我们定义了一个结构体Runner和两种error

var (
	ErrTimeout   = errors.New("connot finish tasks within the timeout")   //超时error
	ErrInterrupt = errors.New("received interrupt from OS")       //中断error
)

type Runner struct {
	interrupt chan os.Signal              //存放中断信号
	complete  chan error	              //放错误
	timeout   <-chan time.Time            //超时信号
	tasks     []func(int)
}


func New(t time.Duration) *Runner {
	return &Runner{
		interrupt: make(chan os.Signal, 1),
		complete:  make(chan error),
		timeout:   time.After(t),
		tasks:     make([]func(int), 0),
	}
}

这里的New函数里,赋给timeout的是一个特殊的单向通道,time.After(t)会在一时间t后返回一个time.Time类型的单向通道,所以我们就通过这个东西来实现计时。

添加任务

func (r *Runner) AddTasks(tasks ...func(int)) {
	r.tasks = append(r.tasks, tasks...)
}

这里的实现很简单,指类的任务是func(int)类型的函数,将函数放到runner的tasks切片中去。

执行任务

func (r *Runner) run() error {
	for id, task := range r.tasks {
		select {
		case <-r.interrupt:
			signal.Stop(r.interrupt)
			return ErrInterrupt
		default:
			task(id)
		}
	}
	return nil
}

func (r *Runner) Start() error {
	signal.Notify(r.interrupt, os.Interrupt)            //这里指定os.Interrupt类型的signals会被送进r.interrupt这个通道
	go func() {
		r.complete <- r.run()
	}()
	select {
	case err := <-r.complete:
		return err
	case <-r.timeout:
		return ErrTimeout
	}
}

Start函数开头的signal.Notify(r.interrupt, os.Interrupt) 的作用是指定os.Interrupt这个类型的signal会被送进r.interrupt这个通道。

后续起一个协程去执行r.run,run会返回error类型到r.complete,所以我们使用select 结合通道,有run中返回的error或者timeout,就返回,如果运行中收到中断,例如ctrl+c,就会停掉

测试一下

func task(id int) {
	time.Sleep(1 * time.Second)
}

func main() {
	runner := runner.New(5 * time.Second)
	runner.AddTasks(task,task,task,task)
	err := runner.Start()
	if err != nil {
		fmt.Println(err.Error())
	}else {
		fmt.Println("完成")
	}
}

执行期间,输入一个ctrl+c,显示如下内容
image-20220623144941816

增加几个task后,会出现这个

image-20220623145048864

其实这个runner中通过time.After()进行计时并不严谨,因为这个计时是从runner对象被创建出来开始的,而不是从开始运行开始的。

posted @ 2022-06-23 15:21  博客是个啥?  阅读(52)  评论(0编辑  收藏  举报