一直做java开发,最近刚接触go,为了更好的学习,尽量把一些基础用的东西自己实现一下,前几天发现go好像没有类似java里的线程池概念,goroutine虽然好用,但也不能一下子开太多。自己写个简单的吧,正好学习一下channel的使用。写在这保存一下,也不知道这样写会有什么问题,毕竟刚开始学,欢迎拍砖。
package pool
import (
"reflect"
"runtime"
)
type zfunc struct {
f interface{}
p []interface{}
}
func (zf *zfunc) invoke() {
kind := reflect.TypeOf(zf.f).Kind()
if kind == reflect.Func {
funcValue := reflect.ValueOf(zf.f)
paramList := make([]reflect.Value, 0)
for _, inter := range zf.p {
paramList = append(paramList, reflect.ValueOf(inter))
}
funcValue.Call(paramList)
}
}
type Zpool struct {
waitCh chan *zfunc
curCh chan int8
}
func New() *Zpool {
p := &Zpool{}
p.curCh = make(chan int8, runtime.NumCPU()*2)
p.waitCh = make(chan *zfunc, runtime.NumCPU()*8)
p.start()
return p
}
func NewWithNum(maxGoroutineNum int, waitQueueNum int) *Zpool {
p := &Zpool{}
p.curCh = make(chan int8, maxGoroutineNum)
p.waitCh = make(chan *zfunc, waitQueueNum)
p.start()
return p
}
func (p *Zpool) GetCurNum() int {
return len(p.curCh)
}
func (p *Zpool) GetWaitNum() int {
return len(p.waitCh)
}
func (p *Zpool) Put(f interface{}, params ...interface{}) {
zf := &zfunc{}
zf.f = f
zf.p = params
p.waitCh <- zf
}
func (p *Zpool) start() {
go func() {
for {
p.curCh <- 1 // occupy a goroutine
go func() {
zf := <-p.waitCh
zf.invoke()
_, ok := <-p.curCh // release a goroutine
if !ok {
panic("pick from curCh error")
}
}()
}
}()
}
测试代码:
package main
import (
"fmt"
"time"
"github.com/wellmoon/go/pool"
)
func main() {
testPool()
time.Sleep(time.Duration(10000) * time.Second)
}
func testPool() {
zpool := pool.New()
for i := 0; i < 100; i++ {
zpool.Put(testFunc, "test", i)
}
for i := 0; i < 10; i++ {
fmt.Println("curNum:", zpool.GetCurNum(), "waitNum:", zpool.GetWaitNum())
time.Sleep(time.Duration(3) * time.Second)
}
}
func testFunc(name string, num int) {
fmt.Println("name:", name, ", num:", num)
time.Sleep(time.Duration(10) * time.Second)
}



