Go再学习_4.Go 最简单的协程池

说明

在 Golang 中要创建一个协程是一件很简单的事情,你只要定义一个函数,并使用 go 关键字去执行它就行了。
如果你接触过其他语言,会发现你在使用使用线程时,为了减少线程频繁创建销毁还来的开销,通常我们会使用线程池来复用线程。

池化技术就是利用复用来提升性能的,那在 Golang 中需要协程池吗
在 Golang 中,goroutine 是一个轻量级的线程,他的创建、调度都是在用户态进行,并不需要进入内核,这意味着创建销毁协程带来的开销是非常小的。因此,在大多数情况下,开发人员是不太需要使用协程池的。

Code

package main

import (
	"fmt"
	"time"
)

type Pool struct {
	work_func chan func()
	work_pool chan struct{}
}

func NewPool(size int) *Pool {
	return &Pool{
		work_func: make(chan func()),
		work_pool: make(chan struct{}, size),
	}
}
func (p *Pool) RunWork(task func()) {
	println("Run task in work runtime")
	defer func() { <-p.work_pool }()
	for {
		task()
		task = <-p.work_func
		println("get a new task from work_func")
	}
}
func (p *Pool) NewTask(task func()) {
	select {
	case p.work_func <- task:
		println("push func to task")
	case p.work_pool <- struct{}{}:
		go p.RunWork(task)
		// Note: 这里不能有break和default,目的就是为了死循环查询状态
	}
}

func main() {
	fmt.Println("main run")
	pool := NewPool(2)

	for i := 1; i < 5; i++ {
		var idx = i
		pool.NewTask(func() {
			time.Sleep(2 * time.Second)
			fmt.Println(idx, time.Now())
		})
	}

	// wait all
	time.Sleep(8 * time.Second)
	/*
	main run
	Run task in work runtime
	Run task in work runtime
	2 2020-08-01 10:27:02.9386028 +0800 CST m=+2.002617801
	1 2020-08-01 10:27:02.9386028 +0800 CST m=+2.002617801
	get a new task from work_func
	push func to task
	push func to task
	get a new task from work_func
	3 2020-08-01 10:27:04.9522576 +0800 CST m=+4.016272601
	4 2020-08-01 10:27:04.9522576 +0800 CST m=+4.016272601
	 */
}

你可能感兴趣的:(Go语言)