如何管理|如何管理 Goroutine
为什么需要管理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 dedicated goroutine managment for
go main
, go func
, go routine pool
, go crontab jobs
.- go main
- go func
- go routine pool
- go crontab jobs
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
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
【如何管理|如何管理 Goroutine】
routine.Crontab
is similar interface like linux system's crontab jobs. You canimport "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...)
}
推荐阅读
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 如何寻找情感问答App的分析切入点
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 2020-04-07vue中Axios的封装和API接口的管理
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus使用queryWrapper如何实现复杂查询
- 如何在Mac中的文件选择框中打开系统隐藏文件夹
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- java中如何实现重建二叉树
- Linux下面如何查看tomcat已经使用多少线程