go并发处理

jobpool:   待处理任务队列
workerpool: 空闲处理者队列
job:        任务类
worker:     处理者类


go: jobpool在前面不断的接收job(jobpool <- job)
go: for: worker从jobpool里循环获取job来处理(select {case job := <-jobpool),
        go: 当来一条job时,就会在workerpool中拿一个空闲的Worker去处理该job,同时此worker在workerpool里消失,
            待此worker处理完后,又会workerpool <- worker(加入到空闲worker队里)。
    当工作池中没有可用的worker时,就会阻塞等待一个空闲的worker(select {case worker := <-wp.WorkerQueue...)
jobpool中如果定义最多放num个待处理的job,就会最多启num个gorouter。
如果jobpool中要定义最多放5 × num个待处理的job,而只允许最多启num个gorouter的话,可设置最大线程数:debug.SetMaxThreads(num)。


// jobpool在前面不断的接收job
go func() {
    for i := 1; i <= num; i++ {
        job := &Job{}
        jobpool <- job
    }
}()

// 循环获取可用的worker,为其分配job来处理
go func() {
    for {
        select {
            case job := <-wp.JobQueue:  // 获取待处理的job
                select {
                    case worker := <-wp.WorkerQueue:  // 获取空闲的worker
                        go worker.run(job)  // 此worker处理此job
                }
        }
    }
}()

原: (转自:https://studygolang.com/articles/17711)

整个过程中,每个Worker都会被运行在一个协程中,
在整个WorkerPool中就会有num个空闲的Worker,
当来一条数据的时候,就会在工作池中去一个空闲的Worker去执行该Job,
当工作池中没有可用的worker时,就会阻塞等待一个空闲的worker。

原code:

[main.go]

package main

import (
    "fmt"
    "runtime"
    "time"
)

type Score struct {
    Num int
}

func (s *Score) Do() {
    fmt.Println("num:", s.Num)
    time.Sleep(1 * 1 * time.Second)
}

func main() {
    num := 100 * 100 * 20
	// debug.SetMaxThreads(num + 1000) //设置最大线程数
		//当数据无限多的时候func (wp *WorkerPool) Run() 会无限创建协程,这里需要做一些处理
	
    // 注册工作池(待处理队列)
    p := NewWorkerPool(num)  // num为worker并发个数,即任务处理者个数
    p.Run()
	
	// 往待处理队列里传入任务
	datanum := 100 * 100 * 100 * 100
    go func() {
        for i := 1; i <= datanum; i++ {
            sc := &Score{Num: i}
            p.JobQueue <- sc
        }
    }()

    for {
        fmt.Println("runtime.NumGoroutine() :", runtime.NumGoroutine())
        time.Sleep(2 * time.Second)
    }

}

[job.go]

package main

type Job interface {
    Do()
}

[worker.go]

package main

type Worker struct {
    JobQueue chan Job
}

func NewWorker() Worker {
    return Worker{JobQueue: make(chan Job)}
}
func (w Worker) Run(wq chan chan Job) {
    go func() {
        for {
            select {
            case job := <-w.JobQueue:
                job.Do()
            }
            wq <- w.JobQueue  //
        }
    }()
}

[workerpool.go]

package main

import "fmt"

待处理队列
type WorkerPool struct {
    workerlen   int  // 任务处理者个数
    JobQueue    chan Job  // 待处理的任务队列
    WorkerQueue chan chan Job  // 每个任务处理者的任务队列
}

func NewWorkerPool(workerlen int) *WorkerPool {
    return &WorkerPool{
        workerlen:   workerlen,
        JobQueue:    make(chan Job),
        WorkerQueue: make(chan chan Job, workerlen),
    }
}
func (wp *WorkerPool) Run() {
	//初始化worker
	fmt.Println("初始化worker")
    for i := 0; i < wp.workerlen; i++ {
        worker := NewWorker()
		worker.Run(wp.WorkerQueue)
			// 调用worker.Run来处理任务
			// 传入WorkerQueue的目的是为了WorkerQueue <- w.JobQueue,相当于在WorkerQueue里注册
	}
	
    // 循环获取可用的worker,往worker中写job
    go func() {
        for {
            select {
            case job := <-wp.JobQueue:
                worker := <-wp.WorkerQueue
                worker <- job
            }
        }
    }()
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值