10.并发模式

来源:互联网 发布:qq飞车莱瑟xa数据 编辑:程序博客网 时间:2024/06/16 20:41

1.runner
这里写图片描述

package mainimport (    "errors"    "os"    "os/signal"    "time")//Runner 在给定的超时时间内执行一组任务//并且在操作系统发送中断信号时结束这些任务type Runner struct {    // interrupt 通道报告从操作系统发送的信号    interrupt chan os.Signal    //complete 通道报告处理任务已经完成    complete chan error    // timeout 报告处理任务已经超时    timeout <- chan time.Time    // tasks 持有一组以索引顺序依次执行的函数    tasks []func(int)}//ErrTimeout 会在任务执行超时时返回var ErrTimeout = errors.New("received timeout")//ErrInterrupt 会在接收到操作系统的事件时返回var ErrInterrupt = errors.New("received interrupt")// New 返回一个新的准备使用的Runnerfunc New(d time.Duration) *Runner {    return &Runner{        interrupt : make(chan os.Signal,1),        complete : make(chan error),        timeout : time.After(d),    }}// Add 将一个任务附加到Runner 上。这个任务是一个//接收一个int 类型的ID 作为参数的函数func (r *Runner) Add(tasks ...func(int)) {    r.tasks = append(r.tasks,tasks...)}//Start 执行所有任务,并监视通道事件func (r *Runner) Start() error {    // 我们希望接收所有中断信号    signal.Notify(r.interrupt,os.Interrupt)    // 用不同的goroutine 执行不同的任务    go func() {        r.complete <- r.run()    }()    select {    // 当任务处理完成时发出的信号    case err := <- r.complete:        return err    //当任务处理程序运行超时时发出的信号    case <-r.timeout:        return ErrTimeout    }}//run 执行每一个已注册的任务func (r *Runner) run() error {    for id, task := range r.tasks {        // 检测操作系统的中断信号        if r.gotInterrupt() {            return ErrInterrupt        }        //执行已注册的任务        task(id)    }    return nil}//gotInterrupt 验证是否接收到了中断信号func (r *Runner) gotInterrupt() bool {    select {    case <-r.interrupt :    //当中断事件被触发时发出的信号        signal.Stop(r.interrupt)        return true    //继续正常运行    default:        return false    }}func main() {}

这里写图片描述


2.pool
这里写图片描述

package poolimport (    "errors"    "log"    "io"    "sync")//Pool 管理一组可以安全地在多个goroutine 间// 共享的资源。被管理的资源必须// 实现 io.Closer 接口type Pool struct {    m sync.Mutex    resources chan io.Closer    factory func() (io.Closer,error)    closed bool}//ErrPoolClosed 表示请求(Acquire)了一个// 已经关闭的池var ErrPoolClosed = errors.New("Pool has been closed.")// New 创建一个用来管理资源的池。// 这个池需要一个可以分配新资源的函数,// 并规定池的大小func New(fn func()(io.Closer,error),size uint) (*Pool,error) {    if size <= 0 {        return nil,errors.New("Size value too small.")    }    return &Pool{        factory : fn,        resources : make(chan io.Closer,size),    },nil}// Acquire 从池中获取一个资源func (p *Pool) Acquire()(io.Closer,error) {    select {    // 检查是否有空闲的资源    case r,ok := <-p.resources:        log.Println("Acquire:","Shared Resource")        if  !ok {            return nil,ErrPoolClosed        }        return r,nil    // 因为没有空闲资源可用,所以提供一个新资源    default :        log.Println("Acquire:","New Resource")        return p.factory()    }}// Release 将一个使用后的资源放回池里func (p *Pool) Release(r io.Closer) {    // 保证本操作和Close 操作的安全    p.m.Lock()    defer p.m.Unlock()    // 如果池已经被关闭,销毁这个资源    if p.closed {        r.Close()        return    }    select {    // 试图将这个资源放入队列    case p.resources <- r:        log.Println("Release : ","In Queue")    // 如果队列已满,则关闭这个资源    default:        log.Println("Release:","Closiing")        r.Close()    }}// Close 会让资源池停止工作,并关闭所有现有的资源func (p *Pool) Close() {    // 保证本操作与Release 操作的安全    p.m.Lock()    defer p.m.Unlock()    // 如果 pool 已经被关闭,什么也不做    if p.closed {        return    }    // 将池关闭    p.closed = true    // 在清空通道里的资源之前,将通道关闭    // 如果不这样做,会发生死锁    close(p.resources)    // 关闭资源    for r := range p.resources {        r.Close()    }}

3.work
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述

原创粉丝点击