本博客与RayXXZhang的博客保持同步更新,转载请注明来自RayXXZhang的博客-Golang实现带优先级的channel
一般Go语言同时使用多个channel
的方法是使用select
/case
语句配合<-
操作符,比如
select {
case <- chan1:
// do something
case <- chan2:
// do something
}
但是这种实现方式下chan1
和chan2
是同等优先级的。如果要实现带优先级的channel
则需要用到defalut
语句。
在go语言中,如果select
/case
中没有default
子句,则程序会阻塞在select
中,直到其中一个case
语句接收到了数据。
如果有default
语句,则不会阻塞,如果case
接收到数据,就执行case
中的语句,如果case
未收到信号,则会执行defalut
中的语句,随后跳出select
块。
使用这个特性可以实现带优先级的channel
队列。以2个优先级的channel
举例,实现方法是使用多层select
,将高优先级channel
放在最外层select
语句的case
后,并跟上一个default
语句以免当高优先级的channel
没有数据时阻塞。
defalut
内依然是一个select
语句,在这个select
语句中,将高优先级和低优先级的case
都放入,并且没有default
语句。这样内层select
就会阻塞直到其中一个case
收到数据。
这种实现方式相当于高优先级的channel
比低优先级的多了一次被处理的机会,即外层select
,只有高优先级没有数据时,才会执行内层select
,此时先产生数据的channel
先被执行。
也就是说,当高优先级和低优先级都有数据时,高优先级先被处理,也就是实现了优先级。示例如下:
for {
select {
case data := <- highChan:
handleHigh(data)
default:
select {
case data := <- highChan:
handleHigh(data)
case data := <- lowChan:
handleLow(data)
}
}
}