• GO协程管理


    协程管理

    goroutine的管理

    • runtime.GOMAXPROCS(2) 分配2个逻辑处理器给调度器使用

    • runtime.Gosched() 当前goroutine从当前线程退出,并放回到队列

    • runtime.NumGoroutine() 查看当前存在的协程数

    • 通过带缓冲的channel可以实现对goroutine数量的控制

      • 控制协程数量代码:

        package main
        
        import (
        	"fmt"
        	"runtime"
        	"time"
        )
        
        type GLimit struct {
        	Limit int
        	ch    chan struct{}
        }
        
        func NewGLimit(limit int) *GLimit {
        	return &GLimit{
        		Limit: limit,
        		ch:    make(chan struct{}, limit),
        	}
        }
        
        func (glimit *GLimit) Run(foo func()) {
        	glimit.ch <- struct{}{}
        	go func() {
        		foo()
        		<-glimit.ch
        	}()
        }
        
        func add() {
        	time.Sleep(100 * time.Millisecond)
        	_ = 4
        }
        
        func main() {
        	ticker := time.NewTicker(1 * time.Second)
        	defer ticker.Stop()
        	go func() {
        		for {
        			<-ticker.C
        			fmt.Printf("go routine number %d\n", runtime.NumGoroutine())
        		}
        	}()
        	gl := NewGLimit(100)
        	for {
        		gl.Run(add)
        	}
        }
        

    优雅地退出守护协程

    • 守护协程:独立于控制终端和用户请求的协程,它一直存在,周期性执行某种任务或等待处理某些发生的事件。伴随着main协程的退出,守护协程也退出。
    • kill命令不是杀死进程,它只是向进程发送信号kill -s pid,s的默认值是15.常见的终止信号如下:
    信号 说明
    SIGINT 2 Ctrl+C触发
    SIGKILL 9 无条件结束程序,不能捕获、阻塞或忽略
    SIGTERM 15 结束程序,可以捕获、阻塞或忽略
    • 监听信号示例代码
    package main
    
    import (
    	"context"
    	"fmt"
    	"net/http"
    	"os"
    	"os/signal"
    	"strconv"
    	"syscall"
    	"time"
    )
    
    var ctx context.Context
    var cancle context.CancelFunc
    
    func init() {
    	ctx, cancle = context.WithCancel(context.Background())
    }
    
    // 监听一个信号
    func listenSignal() {
    	c := make(chan os.Signal)
    	signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
    	for {
    		select {
    		case sig := <-c:
    			fmt.Printf("receive signal %d\n", sig)
    			cancle()
    			return
    		}
    	}
    }
    
    // 监听前端请求
    func listenHttp(port int) {
    	server := &http.Server{Addr: ":" + strconv.Itoa(port), Handler: nil}
    	go func() {
    		for {
    			select {
    			case <-ctx.Done():
    				server.Close()
    				return
    			}
    		}
    	}()
    	server.ListenAndServe()
    	fmt.Printf("stop listen http request on port %d\n", port)
    }
    
    func main() {
    	go listenHttp(8080)
    	go listenHttp(8081)
    	go listenSignal()
    	time.Sleep(10 * time.Second)
    }
    

    协程管理组件

    • go get github.com/x-mod/routine
    • 封装了常规的业务逻辑:初始化、收尾清理、工作协程、守护协程、监听term信号
    • 封装了常见的协程组织形式:并行、串行、定时任务、超时控制、重试、profiling
  • 相关阅读:
    SpringMVC笔记:annotation注解式开发
    HTTP协议状态码详解(HTTP Status Code)
    SpringMVC学习笔记:SpringMVC框架的执行流程
    述一个程序员的技能:系统安装(win7版)idea配置
    Spring扩展:Spring的IoC容器(注入对象的方式和编码方式)
    Spring扩展:Spring框架的由来
    Spring学习笔记:spring整合web之spring-web架包的引用(WebApplicationContextUtils注入容器)
    Spring学习笔记:spring与mybatis四种整合方法
    MySQL修改root密码的多种方法
    为需要远程登录的用户赋予权限:
  • 原文地址:https://www.cnblogs.com/Otiger/p/16221865.html
Copyright © 2020-2023  润新知