如何管理 Goroutine

栏目: Go · 发布时间: 6年前

内容简介:虽然在Golang程序中,使用贴一个常见的资源问题:这段代码可能造成两类对象资源的浪费:

为什么需要管理Goroutines

有效利用资源

虽然在Golang程序中,使用 go func 的方式开启一个 goroutine 协程是非常轻量级的操作。但是,完全不管理的任意创建,会造成很多资源的浪费。虽然golang本身提供了GC功能,但是GC释放是需要时机的。通过更加合理的创建 goroutine 对象可以更加有效的利用系统资源。

贴一个常见的资源问题:

for {
    go func(){
        fmt.Println("xxx")
    }()
}

这段代码可能造成两类对象资源的浪费:

goroutine

以上代码,读者可以长时间运行看看程序对于系统资源的占用情况。

上下文控制

随着程序复杂度的上升, goroutine 通常也会随之增长。如何控制这些新创建的 goroutine 呢。这就需要通过 context.Context 上下文对象,进行父子级传递,完成父子 goroutine 的控制。

如何实现 Goroutine 的管理

除了以上两点原因之外,针对 goroutine 的管理,还可以提供以下功能的扩展:

goroutine pool
go crontab job

具体的实现已经初步实现在该项目 github.com/x-mod/routine 中。

github.com/x-mod/routine

dedicated goroutine managment for go main , go func , go routine pool , go crontab jobs .

  • go main
  • go func
  • go routine pool
  • go crontab jobs

Quick Start

In routine package, it use the Executor interface or ExecutorFunc instance for your implemention.

type Executor interface{
    Execute(context.Context, ...interface{})
}

type ExecutorFunc func(context.Context, ...interface{})

Go Main

routine.Main is the basic function, when use the routine package. The routine.Main does the following things for you:

  • arguments from context
  • support signal interupts
  • support context wait & cancel
import "github.com/x-mod/routine"

func main(){
    routine.Main(routine.WithArguments(context.TODO(), "first arg", "second", false), ExecutorFunc(func(ctx context.Context, args ...interface{}){
        //out put args
        log.Println(args...)

    }), routine.DefaultCancelInterruptors...)
}

# output
# first arg second false

define your own signal interruptor

// InterruptHandler definition
type InterruptHandler func(ctx context.Context, cancel context.CancelFunc) (exit bool)

// Interruptor definition
type Interruptor interface {
    Signal() os.Signal
    Interrupt() InterruptHandler
}

Go Func

routine.Go is the wrapper for the system keyword go , this function should used in the routine.Main scope. It does the following this:

  • sync.wait Add & Done
  • context.Context Done check for executor go routine
import "github.com/x-mod/routine"

func main(){
    routine.Main(context.TODO(), ExecutorFunc(func(ctx context.Context, args ...interface{}){

        routine.Go(routine.WithArguments(ctx, args1...), Executor1)
        routine.Go(routine.WithArguments(ctx, args2...), Executor2)

    }), routine.DefaultCancelInterruptors...)
}

Go routine pool

routine.Pool is the go routine pool manager. you should use it in routine.Main scope either, for the routine.Main controls the routines exiting events. And the routine.Pool does the following things for you:

  • go routines management, like auto create new routine & release idle routine
  • support fixed Executor & dynamic Executor
  • async invoke functions

dynamic executor example:

import "github.com/x-mod/routine"

func main(){

    routine.Main(context.Backgroud(), ExecutorFunc(func(ctx context.Context, args ...interface{}){
        //dynamic executors pool
        pool := routine.NewPool(routine.RunningSize(4), routine.WatingSize(8))
       
        //open
        if err := pool.Open(ctx); err != nil {
            //TODO
            return
        }
        //close
        defer pool.Close()

        //async invoke multiple dynamic executors
        pool.Go(routine.WithArguments(ctx, args1...), executor1)
        pool.Go(routine.WithArguments(ctx, args2...), executor2)

    }), routine.DefaultCancelInterruptors...)
}

fixed executor example:

import "github.com/x-mod/routine"

func main(){

    routine.Main(context.Backgroud(), ExecutorFunc(func(ctx context.Context, args ...interface{}){
       
        //fixed executor pool
        fixedPool := routine.NewPool(routine.RunningSize(4), 
            routine.WatingSize(8),
            routine.FixedExecutor(executor3))
        
        //open
        if err := fixedPool.Open(ctx); err != nil {
            //TODO
            return
        }
        //close
        defer fixedPool.Close()

        //async invoke fixed executor
        fixedPool.Execute(ctx, args1...)
        fixedPool.Execute(ctx, args2...)

    }), routine.DefaultCancelInterruptors...)
}

Go crontab jobs

routine.Crontab is similar interface like linux system's crontab jobs. You can

import "github.com/x-mod/routine"

func main(){
    crontab := routine.NewCrontab(routine.RunningSize(4))
    defer crontab.Close()

    routine.Main(context.Backgroud(), ExecutorFunc(func(ctx context.Context, args ...interface{}){
        
        //open crontab
        if err := crontab.Open(ctx); err != nil {
            //TODO
            return
        }

        // crontab format schedule
        crontab.JOB("* * * * *", executor1).Go(ctx, args1...)
        crontab.JOB("* * * * *", executor2).Go(ctx, args2...)

        // every interval
        crontab.EVERY(time.Second, executor3).Go(ctx, args3 ...)
        crontab.EVERY(time.Minute, executor4).Go(ctx, args4 ...)

        // now, run executor at once
        crontab.NOW(executor5).Go(ctx, args5...)

    }), routine.DefaultCancelInterruptors...)
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

联盟

联盟

里德•霍夫曼、本•卡斯诺查、克里斯•叶 / 路蒙佳 / 中信出版社 / 2015-2-5 / 39.00元

在充满变化的世界,联盟潜在的合伙人 将不确定的行业转变为可掌控的职业生涯 与世界紧密连接,开创精彩的事业与未来 终生效忠于一家公司已经成为历史,我们正在经历的自由雇佣制——将员工看作自由人——无法建立创新所需的高度信任与合作的关系。 互联网时代,企业如何用全新的人才策略定义员工的忠诚?未来职业成功的秘诀是什么? 《联盟》提供了一种使雇主与员工之间从商业交易转变为互惠关......一起来看看 《联盟》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具