Go 通道和 Java BlockingQueue 之间有什么区别吗?两者都是具有相似阻塞和内存模型语义的队列。可选地,两者都可以具有容量集。
4 回答
我想说最大的不同是 Go 通道支持select
语句,它允许你执行一个通道操作。一个例子(从Go 语言规范改变):
select {
case i1 = <-c1:
print("received ", i1, " from c1\n")
case c2 <- i2:
print("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
print("received ", i3, " from c3\n")
} else {
print("c3 is closed\n")
}
}
在此示例中,将执行从 c1 接收、发送到 c2 或从 c3 接收操作中的一个。进入选择时,会随机选择一个就绪通道(如果有)。否则,操作会阻塞,直到其中一个通道准备好。
我不知道使用 Java 实用程序对这个频道选择进行建模的任何简单方法。有人可能会争辩说,这是select
声明的属性,而不是渠道的设计,但我认为这是渠道设计的基础。
另一个非常重要的区别是:您可以关闭 Go 通道以表示没有更多元素即将到来。使用 Java 是不可能的。
示例:goroutine A 读取文件列表。它将每个文件发布到频道中。在最后一个文件之后,它会关闭通道。goroutine B 从通道中读取文件并以某种方式处理它们。通道关闭后,goroutine 退出。
在 Java 中做到这一点并不容易。但是存在一些解决方法。
它们可以以类似的方式使用。
- 两者都可以在放置/发送或接收/接收时阻止。
- 两者都具有控制发送何时阻塞的能力。
最大的区别可能是 go 通道比 java 对象便宜得多。并且可以将 go 通道限制为仅发送或仅接收,这可以确保有关谁可以发送以及谁可以从通道接收的一些附加类型强制执行。
要在 java 中执行类似于 golang'select 语句的操作,需要使用 java.nio 包。特别是选择器和通道。在此处查看软件包文档:
http://docs.oracle.com/javase/6/docs/api/java/nio/channels/package-summary.html#multiplex
它提供与 golang select 语句几乎相同的功能,使用单个线程从多个通道多路读取/写入。