17

Are there any differences between a Go channel and a Java BlockingQueue? Both are queues with similar blocking and memory model semantics. Optionally both can have a capacity set.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
rrevo
  • 1,647
  • 1
  • 16
  • 22

4 Answers4

22

I would say the biggest difference is that Go channels have support for the select statement, which allow you to perform exactly one channel operation. An example (altered from the 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")
    }
}

In this example, exactly one of the receive-from-c1, send-to-c2, or receive-from-c3 operations will be performed. When entering the select, a ready channel (if any) is selected randomly. Otherwise, the operation blocks until one of the channels is ready.

I'm not aware of any trivial way to model this channel selection using the Java utilities. One could argue that this is a property of the select statement rather than the design of channels, but I would argue that it's fundamental to the design of channels.

Brett Kail
  • 33,593
  • 2
  • 85
  • 90
  • 1
    I think you could get close using the poll method on a blocking queue. But you are right that the select statement gives syntactic support for multiplexing over a number of different channels. – Jeremy Wall May 22 '12 at 16:38
  • 2
    Right, I didn't mention busy-wait because I consider that a non-solution :-). – Brett Kail May 22 '12 at 17:41
10

One more very important difference is: You can close a Go channel to signal that no more elements are coming. That is not possible using Java.

Example: goroutine A reads a list of files. It posts each file into the Channel. After the last file, it closes the channel. goroutine B reads the files from the channel and processes them in some way. After the channel is closed, the goroutine quits.

Doing this in Java is not easily possible; however some workarounds exist.

Kosta
  • 812
  • 1
  • 7
  • 13
  • 5
    Indeed! This is a very important difference. With Java, you need to send some kind of poison record or end-of-stream character to signal that no more items are coming. This requires additional code on both sides, see [javadoc of BlockingQueue](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html): `a common tactic is for producers to insert special end-of-stream or poison objects, that are interpreted accordingly when taken by consumers.` – Mahmoud Ben Hassine Nov 17 '16 at 12:31
  • does anybody know why BQ not implemented close? It looks like something simple but useful and essential – Sergey Ponomarev Nov 23 '20 at 21:53
4

They can be used in similar ways.

  • Both can block on when putting/sending or taking/recieving.
  • Both have a capacity that governs when sending will block.

The biggest differences are probably that go channels are considerably cheaper than a java object. and that go channels can be restricted to only send or only receive which can ensure some additional type enforcement regarding who can send and who can receive from a channel.

Jeremy Wall
  • 23,907
  • 5
  • 55
  • 73
  • 3
    Do you have source to show that they are that much cheaper? It's not that I don't believe you but I would not be surprised if some of Java's queues and nio channels could keep up in terms of execution time. I'm sure Java looses on the memory front though. – Adam Gent Feb 05 '15 at 09:56
  • @AdamGent I'm afraid I don't have any sources on hand. I was primarily talking about memory not execution speed though. – Jeremy Wall Feb 05 '15 at 20:11
3

To do something similar to golang'select statement in java would involve using the java.nio package. Specifically selectors and channels. Check out the package docs here:

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

It offers pretty much the same capability as the golang select statement, using a single thread to multiplex reading/writing from multiple channels.

  • 3
    Go channels allow arbitrary data structures (including pointers) to be transferred, but java.nio.channels only allows bytes to be transferred. I don't think they are really comparable. – Brett Kail Oct 06 '15 at 14:51