监控goroutine的执行
select类似switch case语句,select的功能和Linux的ip的select、poll、epoll相似。==主要作用于多个channel==
eg:有两个goroutine都在执行,在主的gotoutine中,当某一个执行完成后需要立马得到反馈
var done bool
var lock sync.Mutex
func g1() {
time.Sleep(time.Second)
lock.Lock()
defer lock.Unlock()
done = true
}
func g2() {
time.Sleep(time.Second * 2)
lock.Lock()
defer lock.Unlock()
done = true
}
func main() {
go g1()
go g2()
for {
if done {
fmt.Println("done")
time.Sleep(time.Millisecond * 10)
return
}
}
}
a.select完成多个channel的监控
var done = make(chan struct{})
func g1() {
time.Sleep(time.Second)
done <- struct{}{}
}
func g2() {
time.Sleep(time.Second * 2)
done <- struct{}{}
}
func main() {
go g1()
go g2()
<-done
fmt.Println("done") //只能知道有goroutine down了但是不知道哪一个
}
监控多个不同的goroutine,不使用全局channel
select监控多个channel,每个channel返回都知道。==某一个分支就绪就执行该分支,若果两个都就绪,随机执行==
func g1(ch chan struct{}) {
time.Sleep(time.Second * 2)
ch <- struct{}{}
}
func g2(ch chan struct{}) {
time.Sleep(time.Second * 1)
ch <- struct{}{}
}
func main() {
g1ch := make(chan struct{})
g2ch := make(chan struct{})
go g1(g1ch)
go g2(g2ch)
select {
case <-g1ch:
fmt.Println("g1 down")
case <-g2ch:
fmt.Println("g2 down")
}
}
g2 down //取决于函数sleep
b.select default防止阻塞
select {
case <-g1ch:
fmt.Println("g1 down")
case <-g2ch:
fmt.Println("g2 down")
default:
fmt.Println("default")
} //其他函数通常没有执行的机会
default设置执行时间
select {
case <-g1ch:
fmt.Println("g1 down")
case <-g2ch:
fmt.Println("g2 down")
default:
time.Sleep(time.Second * 5) //只留给case总共五秒钟时间
fmt.Println("default")
}
c.Timer
func g1(ch chan struct{}) {
time.Sleep(time.Second * 2)
ch <- struct{}{}
}
func g2(ch chan struct{}) {
time.Sleep(time.Second * 1)
ch <- struct{}{}
}
func main() {
g1ch := make(chan struct{})
g2ch := make(chan struct{})
go g1(g1ch)
go g2(g2ch)
tm := time.NewTimer(5 * time.Second) //default默认退出时间
for {
select {
case <-g1ch:
fmt.Println("g1 down")
case <-g2ch:
fmt.Println("g2 down")
case <-tm.C:
fmt.Println("time out")
return //如果不return,循环将继续执行,会导致死锁
}
}
}
评论