go并发应用 - 写一个任务调度小程序

  • 程序可以在分配的时间内完成工作,正常终止;
  • 程序没有及时完成工作,“自杀”;
  • 接收到操作系统发送的中断事件,程序立刻试图清理状态并停止工作
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语言实战

你可能感兴趣的:(go并发应用 - 写一个任务调度小程序)