Golang 开发者首页投稿(暂停使用,暂停投稿)程序员

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

2017-08-04  本文已影响189人  ouyangan
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语言实战

上一篇 下一篇

猜你喜欢

热点阅读