Go channel vs Java BlockingQueue

rre*_*evo 12 java concurrency channel go

Go通道和Java BlockingQueue之间有什么区别吗?两者都是具有类似阻塞和内存模型语义的队列.可选地,两者都可以具有容量集.

Bre*_*ail 15

我想说最大的区别是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")
    }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,将执行从c1接收,从c1发送到c2或从c3接收操作中的一个.进入选择时,随机选择就绪通道(如果有).否则,操作将阻塞,直到其中一个通道准备就绪.

我不知道使用Java实用程序对这个通道选择建模的任何简单方法.有人可能会说这是select声明的属性而不是频道的设计,但我认为它是频道设计的基础.

  • 是的,我没有提到忙等待,因为我认为这是一个非解决方案:-)。 (2认同)

Kos*_*sta 7

另一个非常重要的区别是:您可以关闭Go通道以表示不再有元素到来.使用Java是不可能的.

示例:goroutine A读取文件列表.它将每个文件发布到频道.在最后一个文件之后,它关闭了频道.goroutine B从通道读取文件并以某种方式处理它们.通道关闭后,goroutine退出.

用Java做这件事并不容易; 但是存在一些变通方法.

  • 确实!这是非常重要的区别。使用Java,您需要发送某种中毒记录或流尾字符,以表示不再有其他项目。这需要双方都附加代码,请参见[BlockingQueue的javadoc](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html):`常见的策略是生产者插入特殊的流结束对象或有毒对象,这些对象在被消费者拿走时会被相应地解释。 (2认同)