2012-05-21 43 views
7

Go频道和Java BlockingQueue之间有什么区别吗?两者都是具有相似阻塞和内存模型语义的队列。可选地,两者都可以具有容量设定。Go频道vs Java BlockingQueue

回答

12

我会说最大的不同是Go通道支持select语句,它允许您执行一个通道操作。一个例子(从Go language specification改变的):

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实用程序对此通道选择进行建模的任何微不足道的方法。有人可能会争辩说,这是陈述的属性,而不是渠道的设计,但我认为这是渠道设计的基础。

+1

我想你可以在阻塞队列上使用poll方法关闭。但是你说得对,select语句为多种不同渠道的复用提供了语法支持。 –

+1

对,我没有提到忙等待,因为我认为这是一个非解决方案:-)。 –

2

它们可以以类似的方式使用。

  • 这两者都可以阻止在发送/发送或接受/接收。
  • 两者都有一个容量管理发送将阻止。

最大的区别可能在于,通道比java对象便宜得多。并且可以将频道限制为仅发送或仅接收,这可以确保关于谁可以发送以及谁可以从频道接收的一些附加类型强制执行。

+1

您是否有资料显示他们便宜得多?这并不是说我不相信你,但是如果一些Java的队列和nio频道能够跟上执行时间,我不会感到惊讶。不过,我确信Java在内存方面有所松动。 –

+0

@AdamGent恐怕我手头没有任何资源。尽管我主要谈论内存不是执行速度。 –

3

在java中执行类似golang'select语句的操作需要使用java.nio包。具体选择器和频道。点击这里,查看包文档:

http://docs.oracle.com/javase/6/docs/api/java/nio/channels/package-summary.html#multiplex

它提供了几乎相同的能力为golang select语句,使用单线程复读/从多个渠道写作。

+2

Go通道允许传输任意数据结构(包括指针),但java.nio.channels只允许传输字节。我不认为他们真的可比。 –

5

还有一个非常重要的区别是:您可以关闭一个Go频道,以表示没有更多元素即将到来。这是不可能的使用Java。

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

用Java做这件事并不容易;但是存在一些解决方法。

+1

确实!这是一个非常重要的区别。使用Java,您需要发送某种有毒记录或流式结束字符,以表示没有更多项目即将到来。这需要在双方都有额外的代码,参见[BlockingQueue的javadoc](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html): '一种常见的策略是为了让生产者插入特殊的流结束或毒物,并在消费者接受时进行相应的解释 –