zoukankan      html  css  js  c++  java
  • golang 固定worker 工作池

    服务器编程使用最多的就是通过线程池提升服务的并发执行能力,在go语言中,一样可以轻松的构建固定数目的goroutine作为线程池,下面通过计算多个整数的和来说明这种并发范式。

    设计思路:

     除了主要的main goroutine ,还需开启以下几类goroutine

       1,初始化任务的goroutine

       2,分发任务的goroutine

       3,等到所有work结束,然后关闭所有通道的goroutine

    main主要负责拉起以上的goroutine 冰火取结果

     程序还需要三个通道

      1,传递task任务的通道

      2,传递task结果的通道

     3 ,接收workder处理完任务后所发送通知的通道

    具体代码如下

    package go_worker
    
    import (
        "fmt"
    )
    
    //定义工作数量
    const (
        WORKS=5
    )
    
    //定义工作任务结构体,可根据需求改变
    type task struct {
        begin int
        end int
        result  chan<- int
    }
    //定义执行任务的方法,可根据需求更改
    func (t *task) do(){
        sum:=0
        for i:=t.begin;i<=t.end;i++{
            sum++
        }
        t.result<-sum
    }
    
    //入口函数
    
    func main(){
        works:=WORKS
        //定义工作通道
        taskchan:=make(chan task,10)
        //定义结果通道
        resultchan:=make(chan int,10)
        //work工作信号通道
        done:=make(chan struct{},10)
        //初始化task的goroutine
        go initTask(taskchan,resultchan,100);
        //分发任务到协程池
        distributeTask(taskchan,works,done)
        //获取goroutine处理完成任务通知,并关闭通道
        go closeResult(done,resultchan,works)
        //通过结果通道,获取结果并汇总
        sum:=processResult(resultchan)
        fmt.Println("sum=",sum)
    }
    //初始化task chan
    func initTask(taskchan chan<-task,r chan int ,p int){
        qu:=p/10
        mod:=p%10
        high:=qu*10;
        for j:=0;j<qu;j++{
            b:=10*j+1
            e:=10*(j+1)
            task:=task{
                begin:b,
                end:e,
                result:r,
            }
            taskchan<-task
        }
        if mod!=0{
            task:=task{
                begin:high+1,
                end:p,
                result:r,
            }
            taskchan<-task
        }
        close(taskchan)
    }
    
    //读取taskchan 并分发到worker goRoutine处理,总数量为workers
    func distributeTask(taskchan<-chan task,workers int ,done chan struct{}){
        for i:=0;i<workers;i++{
            go processTask(taskchan,done)
        }
    }
    //工作goroutine处理的具体内容,并将处理的结果发送到结果chan
    func processTask(taskchan <-chan task,done chan struct{}){
        for t:=range taskchan{
            t.do()
        }
        done<- struct{}{}
    }
    
    //通过done channel同步等待所有工作goroutine的结束,然后关闭结果chan
    func closeResult(done chan struct{},resultchan chan int ,workers int ){
        for i:=0;i<workers;i++{
            <-done
        }
        close(done)
        close(resultchan)
    }
    
    //读取结果通道汇聚结果
    
    func processResult(resultchan chan int )int{
        sum:=0
        for r:=range resultchan{
            sum+=r
        }
        return sum
    }

    ok ,至此,程序结束,可将task和task.do() 替换成自己的已有逻辑执行

  • 相关阅读:
    java的多线程学习,第二记
    java多线程的学习
    长城
    2018-12-6
    mysql的笔记
    springboot用jpa生成表,没有外键
    idea 使用方法
    Oracle数据库中文乱码问题
    JAVA-Could not create the Java virtual machine java启动失败
    log4j日志如何在ssh中配置?
  • 原文地址:https://www.cnblogs.com/tsxylhs/p/13526925.html
Copyright © 2011-2022 走看看