转投go系列-go需要线程池吗?

GMP调度模型,不做过多赘述。

那么Golang 已经实现了 M:N 的用户态携程Goroutine,还要必要在 Golang 里实现goroutine池吗?

个人感觉还是必要的,因为在某些情况下还是要限制一下并发量的。
同时就算goroutine的开销低,当对性能要求高,并且goroutine里面执行的操作时间极小时,频繁创建goroutine进行调用也是不可取的。

接下来实现一个控制并发量的pool,但是不保存goroutine。比较适合小项目。

package pool

import (
	"fmt"
	"time"
)

func NewGoPool(queueMax int, workerCount int) *GoPool {
	taskQueue := taskQueue{}
	taskQueue.create(queueMax)
	slavePool := slavePool{}
	slavePool.create(workerCount)
	return &GoPool{taskQueue: taskQueue, slavePool: slavePool}
}

type GoPool struct {
	taskQueue taskQueue
	slavePool slavePool
	stop      chan struct{}
}

func (gp *GoPool) AddTask(task func(), wait time.Duration) bool {
	return gp.taskQueue.addTask(task, wait)
}

func (gp *GoPool) StartRun() {
	go func() {
		for {
			select {
			case job := <-gp.taskQueue.tasks:
				slave := <-gp.slavePool.slaves
				slave.job <- job
			case <-gp.stop:
				for i := 0; i < cap(gp.slavePool.slaves); i++ {
					slave := <-gp.slavePool.slaves

					slave.stop <- struct{}{}
					<-slave.stop
				}

				gp.stop <- struct{}{}
				return
			}
		}
	}()
}

func (gp *GoPool) Stop() {
	gp.stop <- struct{}{}
	<-gp.stop
}

type taskQueue struct {
	tasks chan func()
}

func (tq *taskQueue) create(max int) {
	tq.tasks = make(chan func(), max)
}

func (tq *taskQueue) addTask(task func(), wait time.Duration) bool {
	timeout := make(chan bool, 1)
	go func() {
		time.Sleep(wait)
		timeout <- true
	}()

	select {
	case tq.tasks <- task:
		return true
	case <-timeout:
		return false
	}
}

type slavePool struct {
	slaves chan *slave
}

func (sp *slavePool) create(max int) {
	sp.slaves = make(chan *slave, max)
	for i := 0; i < cap(sp.slaves); i++ {
		sla := slave{parentPool: sp}
		sla.job = make(chan func())
		sla.stop = make(chan struct{})
		sla.start()
	}
}

type slave struct {
	parentPool *slavePool
	job        chan func()
	stop       chan struct{}
}

func (s *slave) start() {
	go func() {
		for {
			// worker free, add it to pool
			s.parentPool.slaves <- s
			select {
			case job := <-s.job:
				fmt.Println("do job")
				job()

			case <-s.stop:
				s.stop <- struct{}{}
				return
			}
		}
	}()
}

main.go

package main

import (
	"fmt"
	"simontest/pool"
	"time"
)

func main() {
	goPool := pool.NewGoPool(2, 1)
	goPool.StartRun()
	for i := 0; i < 106; i++ {
		count := i

		res := goPool.AddTask(func() {
			fmt.Printf("I am task! Number %d\n")
		}, 3*time.Second)

		fmt.Printf("I am save! Number %d  %v\n", count, res)
	}
	
	time.Sleep(1000 * time.Second)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值