在golang中,我们可以很轻易产生数以万计的goroutine,不过这也带来了麻烦:在运行中某一个goroutine异常退出,怎么办?
在erlang中,有link原语,2个进程可以链接在一起,一个在异常退出的时候,向另一个进程呼喊崩溃的原因,然后由另一个进程处理这些信号,包括是否重启这个进程。在这方面,erlang的确做得很好,估计以后这个特性会在golang中得到实现。
由此得到启发,我写了一个简单的程序,监控goroutine异常退出。
package main
import (
"log"
"runtime"
"math/rand"
"time"
)
type message struct {
normal bool //true means exit normal, otherwise
state map[string]interface{} //goroutine state
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
mess := make(chan message, 10)
for i := 0; i < 100; i++ {
go worker(mess)
}
supervisor(mess)
}
func worker(mess chan message) {
defer func() {
exit_message := message{state:make(map[string] interface{})}
i := recover()
if i != nil {
exit_message.normal = false
} else {
exit_message.normal = true
}
mess <- exit_message
}()
now := time.Now()
seed := now.UnixNano()
rand.Seed(seed)
num := rand.Int63()
if num % 2 != 0 {
panic("not evening")
} else {
runtime.Goexit()
}
}
func supervisor(mess chan message) {
for i := 0; i < 100; i++ {
m := <- mess
switch m.normal {
case true :
log.Println("exit normal, nothing serious!")
case false:
log.Println("exit abnormal, something went wrong")
}
}
}
原本是想把goroutine异常退出时的状态,也就是某些变量保存到message中的state,然后在另一个goroutine里面处理这些数据,不过能力有限,暂时做不出来,以后会完善的。这里只验证goroutine在异常退出的时候,向另一个goroutine发送信号。
在worker函数里面,会判断随机数是不是偶数,不是的话会使用panic异常退出,然后使用defer向supervisor发送信号,supervisor接受到就输出结果。
下面看一下效果:
我们用了100个goroutine,也就有100个退出信号。由图可以得到我们的程序运行良好。
转贴请注明来自:格通