- 程序可以在分配的时间内完成工作,正常终止;
- 程序没有及时完成工作,“自杀”;
- 接收到操作系统发送的中断事件,程序立刻试图清理状态并停止工作
package main
import (
"errors"
"fmt"
"os"
"os/signal"
"time"
)
func main() {
runner := New(time.Duration(1) * time.Second).Add(func(i int) {
fmt.Println(i)
time.Sleep(time.Duration(2) * time.Second)
})
err := runner.Start()
if err != nil {
fmt.Println(err)
}
}
type Runner struct {
interrupt chan os.Signal
complete chan error
timeout <-chan time.Time
tasks []func(int)
}
var ErrTimeOut = errors.New("task timeout")
var ErrInterrupt = errors.New("task interrupt")
func New(d time.Duration) *Runner {
return &Runner{
interrupt: make(chan os.Signal, 1),
complete: make(chan error),
timeout: time.After(d),
}
}
func (r *Runner) Add(tasks ...func(int)) *Runner {
r.tasks = append(r.tasks, tasks...)
return r
}
func (r *Runner) Start() error {
signal.Notify(r.interrupt, os.Interrupt)
go func() {
r.complete <- r.run()
}()
select {
case err := <-r.complete:
fmt.Println("任务执行完毕")
return err
case <-r.timeout:
fmt.Println("任务超时")
return ErrTimeOut
}
}
func (r *Runner) run() error {
for id, task := range r.tasks {
if r.gotInterrupt() {
return ErrInterrupt
}
task(id)
}
return nil
}
func (r *Runner) gotInterrupt() bool {
select {
case <-r.interrupt:
signal.Stop(r.interrupt)
return true
default:
return false
}
}
参考书籍:go语言实战
网友评论