├── .gitignore ├── README.md ├── config └── config.go ├── executors └── executors.go └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | bin/ 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoExecutors 2 | 一个Java ExecutorService风格的Go语言并发库。 3 | go run main.go 4 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func DefaultGoroutinesNum() int32 { 8 | return 100 9 | } 10 | 11 | func LoadConfig() { 12 | fmt.Println("config loaded.") 13 | } 14 | -------------------------------------------------------------------------------- /executors/executors.go: -------------------------------------------------------------------------------- 1 | package executors 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync/atomic" 7 | "time" 8 | 9 | "github.com/linkerlin/GoExecutors/config" 10 | ) 11 | 12 | type ErrorTimeout string 13 | 14 | func (e ErrorTimeout) Error() string { return string(e) } 15 | 16 | type Callable func() (interface{}, error) // result + error 17 | type FutureQ chan *Future 18 | 19 | type Executors struct { 20 | futureQ FutureQ 21 | goNum int32 22 | running int32 23 | } 24 | 25 | type Future struct { 26 | retChan chan interface{} 27 | errorChan chan error 28 | exceptionChan chan interface{} 29 | callable Callable 30 | } 31 | 32 | func (f *Future) GetResult(timeout time.Duration) (ret interface{}, timeoutError error, err error, exception interface{}) { 33 | timer := time.NewTimer(timeout) 34 | // fmt.Println("future对应的结果chan:", f.retChan) 35 | select { 36 | case exception = <-f.exceptionChan: 37 | fmt.Println("future 获取到了异常:", exception) 38 | return nil, nil, nil, exception 39 | case err = <-f.errorChan: 40 | fmt.Println("future 获取到了错误:", err) 41 | return nil, nil, err, nil 42 | case ret = <-f.retChan: 43 | fmt.Println("future 获取到了结果:", ret) 44 | return ret, nil, nil, nil 45 | case <-timer.C: 46 | return nil, ErrorTimeout("Callable执行超时错误!"), nil, nil 47 | } 48 | } 49 | 50 | func NewExecutors() *Executors { 51 | var fq = make(FutureQ, 100) 52 | var es = &Executors{fq, 0, 1} 53 | var goMainFunc = func() { 54 | atomic.AddInt32(&es.goNum, 1) 55 | defer atomic.AddInt32(&es.goNum, -1) 56 | for atomic.LoadInt32(&es.running) == 1 { 57 | var err interface{} 58 | select { 59 | case future := <-fq: 60 | defer func() { 61 | if err = recover(); err != nil { 62 | fmt.Errorf("捕获了一个错误:%v", err) 63 | future.exceptionChan <- err 64 | } 65 | }() 66 | ret, callableError := future.callable() 67 | // fmt.Println("result chan:", retChan) 68 | if callableError != nil { 69 | future.errorChan <- callableError 70 | } else if ret != nil { 71 | future.retChan <- ret 72 | } 73 | case <-time.After(time.Second * 1): 74 | runtime.Gosched() 75 | if es.GetGoNum() > config.DefaultGoroutinesNum() { 76 | fmt.Println("idle gorotine.", es.GetGoNum()) 77 | runtime.Goexit() 78 | } 79 | } 80 | // fmt.Println(".") 81 | } 82 | } 83 | var i int32 = 0 84 | for ; i < config.DefaultGoroutinesNum(); i++ { 85 | go goMainFunc() 86 | } 87 | es.ControlGoNum(goMainFunc) 88 | 89 | return es 90 | 91 | } 92 | 93 | func (es *Executors) ControlGoNum(goMainFunc func()) { 94 | go func() { 95 | for atomic.LoadInt32(&es.running) == 1 { 96 | runtime.Gosched() 97 | if es.GetGoNum() < config.DefaultGoroutinesNum() || len(es.futureQ) > 10 { 98 | runtime.Gosched() 99 | if es.GetGoNum() < config.DefaultGoroutinesNum() || len(es.futureQ) > 10 { 100 | fmt.Println("GoNum:", es.GetGoNum(), "len(es.futureQ):", len(es.futureQ)) 101 | go goMainFunc() 102 | go goMainFunc() 103 | go goMainFunc() 104 | go goMainFunc() 105 | go goMainFunc() 106 | runtime.Gosched() 107 | } 108 | } else { 109 | time.Sleep(time.Millisecond * 200) 110 | runtime.Gosched() 111 | } 112 | } 113 | }() 114 | } 115 | 116 | func (es *Executors) GetGoNum() int32 { 117 | return atomic.LoadInt32(&es.goNum) 118 | } 119 | 120 | func (es *Executors) Stop() { 121 | atomic.StoreInt32(&es.running, 0) 122 | } 123 | 124 | func (es *Executors) Submit(callable Callable) *Future { 125 | retChan := make(chan interface{}, 1) 126 | errorChan := make(chan error, 1) 127 | exceptionChan := make(chan interface{}, 1) 128 | future := &Future{retChan, errorChan, exceptionChan, callable} 129 | es.futureQ <- future 130 | return future 131 | } 132 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "runtime" 7 | "time" 8 | 9 | "github.com/linkerlin/GoExecutors/config" 10 | "github.com/linkerlin/GoExecutors/executors" 11 | ) 12 | 13 | func main() { 14 | config.LoadConfig() 15 | fmt.Println("Default goroutines number is ", config.DefaultGoroutinesNum()) 16 | es := executors.NewExecutors() 17 | f := func() (interface{}, error) { 18 | fmt.Println("这是从一个Callable内部发出的声音。") 19 | // time.Sleep(time.Second * 1) 20 | return 1, nil 21 | } 22 | 23 | var future = es.Submit(f) 24 | var ret, t, e, ex = future.GetResult(time.Millisecond * 1500) 25 | switch { 26 | case ex != nil: 27 | fmt.Println("异常", ex) 28 | case t == nil && e == nil: 29 | fmt.Println("No.1 正常", ret) 30 | case t != nil: 31 | fmt.Println("超时!") 32 | case e != nil: 33 | fmt.Println("出错", e) 34 | default: 35 | fmt.Println("不会到这里", ret) 36 | } 37 | fTimeout := func() (interface{}, error) { 38 | time.Sleep(time.Second * 1) 39 | fmt.Println("这是第二次从Callable内部发出的声音。") 40 | return 2, errors.New("1s") 41 | } 42 | fmt.Println("=================") 43 | time.Sleep(100) 44 | future = es.Submit(fTimeout) 45 | ret2, t, err, ex := future.GetResult(time.Millisecond * 500) 46 | switch { 47 | case ex != nil: 48 | fmt.Println("异常", ex) 49 | case t == nil && err == nil: 50 | fmt.Println("执行成功", ret2) 51 | case err != nil: 52 | fmt.Println("执行出错", err) 53 | case t != nil: 54 | fmt.Println("No.2 超时!", t) 55 | default: 56 | fmt.Println("不会到这里", ret2) 57 | } 58 | fPanic := func() (interface{}, error) { 59 | fmt.Println("这是第三次从Callable内部发出的声音。") 60 | panic(100) 61 | } 62 | for i := 0; i < 3; i++ { 63 | future = es.Submit(fPanic) 64 | } 65 | 66 | ret3, t, err, ex := future.GetResult(time.Millisecond * 500) 67 | switch { 68 | case ex != nil: 69 | fmt.Printf("No.3 异常 %d\n", es.GetGoNum()) 70 | case err == nil && t == nil: 71 | fmt.Println("执行失败,没有捕获到错误", ret3) 72 | case t != nil: 73 | fmt.Println("执行失败,超时", t) 74 | case err != nil: 75 | fmt.Println("执行成功,捕获到", err) 76 | default: 77 | fmt.Println("不会到这里", ret3) 78 | } 79 | 80 | f = func() (interface{}, error) { 81 | fmt.Println("这是从No.4 Callable内部发出的声音。", es.GetGoNum()) 82 | // time.Sleep(time.Second * 1) 83 | return 1, errors.New("😀") 84 | } 85 | 86 | future = es.Submit(f) 87 | ret, t, e, ex = future.GetResult(time.Millisecond * 1500) 88 | switch { 89 | case ex != nil: 90 | fmt.Println("异常", ex) 91 | case t == nil && e == nil: 92 | fmt.Println("正常", ret) 93 | case t != nil: 94 | fmt.Println("超时!") 95 | case e != nil: 96 | fmt.Println("No.4 出错", e) 97 | default: 98 | fmt.Println("不会到这里", ret) 99 | } 100 | fmt.Println("GoNum:", es.GetGoNum()) 101 | time.Sleep(time.Second * 3) 102 | fmt.Println("GoNum:", es.GetGoNum()) 103 | es.Stop() 104 | for es.GetGoNum() > 0 { 105 | runtime.Gosched() 106 | fmt.Println("GoNum:", es.GetGoNum()) 107 | time.Sleep(time.Millisecond * 100) 108 | } 109 | fmt.Println("GoNum:", es.GetGoNum()) 110 | } 111 | --------------------------------------------------------------------------------