在Clojure / Java中相当于Goroutines

I recently enjoyed watching the Google IO talk on Go Concurrency patterns

Although the Go approach to concurrency (groutines, communication over channels) is clearly different to Clojure (immutability, manged references, STM), it seemed like the Go approach could still be useful in some circumstances in a Clojure context.

So is there a direct equivalent in Clojure or Java for Go's concurrency primitives (perhaps a library), in particular:

  • channel-like objects that block until a reader and writer are available at both ends
  • A select-like construct that can wait for results on multiple channels

P.S. Perfectly happy with a Java solution since it would be easy to use from Clojure

UPDATE Since the question was originally asked, Clojure now has core.async which provides all this functionality and more.

You should check out core.async. It is a library written by Rich Hickey that implements go style channels.

Without knowing anything about Go, have a look at Lamina to see if it fits what you are looking for https://github.com/ztellman/lamina

Take a look at Joxa. It is a Clojure-like dialect of Lisp targeting Erlang Virtual Machine.

And Erlang is known for light-weight sub-1000-bytes processes.

Also Erjang is somewhat related and could be of interest to you. It's an implementation of Erlang Virtual Machine on top of JVM.

So theoretically you can compile Joxa to BEAM and then still run it on JVM. Not that I would recommend it :-).

channel-like objects that block until a reader and writer are available at both ends

This is a bit confusing. Do you mean "blocks until, if writing, a reader is available or, if reading, a writer is available"? I am speaking on behalf of the threads and not the construct, a construct cannot block only threads can. (To avoid confusion a construct would instruct threads to block).

If my assumption is true there are two options you can have (in standard Java).

  1. SynchronousQueue
  2. TransferQueue (though this can be used as a buffer channel also)

A select-like construct that can wait for results on multiple channels

As far as I know there arent any true select like constructs. The closest you can have is a ExecutorCompletionService that will return when the next available task submitted is completed.

the akka actor ~= goroutine+channel

I highly recommend JCSP, based on the Occam/transputer algorithms. Key parts of this API implementation have been checked for correctness using formal methods and formal prover algorithms, so are about as reliable as is possible (the Alternative class is the prime achievement in this regard).

JCSP is very good ... however the downside remains the limitations imposed by the JVM, especially the high cost of threads. In Go or Occam, threads can number in millions, but not so on the JVM.

I have recently written go-lightly, a Clojure library to support programming with Go concurrency constructs, putting some Clojure idioms on that concurrent programming style.

The core constructs of Go concurrency programming are:

  1. Go routines
  2. Synchronous (blocking) channels
  3. Bounded, mostly asynchronous (non-blocking) channels
  4. A select operator that reads the next available message from multiple channels
  5. Timeout operations on channel read/writes/selects

The go-lightly library has all of these features, building on top of features available in Java and Clojure. True Go routines are multiplexed onto threads, rather than fully using a thread for its full lifetime. In go-lightly, I build go routines on top of the Clojure future macro, so this is the weakest part of the Go model on the JVM.

I tried using lamina, but it lacks bounded channels (which you might want in some scenarios and is a part of the Go buffered channel model) and as far as I can tell lacks a way to have a producer block when putting a message onto a channel. That is a crucial feature of the Go concurrency model.

I've included a number of examples using the go-lightly library in the git repo. Most are based on examples that Rob Pike has given in talks over the past two years.

It would be interesting to build a Clojure library on top of JCSP, but I haven't researched that yet.

You might want to look at Quasar/Pulsar. It's very new, but it's exactly what you're looking for.