I guess I’ll take a minute to throw in some of my opinions here. The TL;DR version is that I find Scala to be a much better language for programming parallelism than Java. That isn’t because it has better libraries though, it is because it is a more powerful language that stresses a functional style.
The bottom line is that anything you do in Scala in terms of parallelism could be done in Java. Every library supporting parallelism in Scala is either also available in Java, like Akka, or has equivalents in Java, like parallel collections and composable Futures. The way you interact with those libraries is different though. I’ll start with a simple example using a parallel collection. Here’s the Scala code.
val mappedSum = values.par.map(f).sum
How this translates to Java varies a bit depending on the type of values, whether it is an array or a List and issues with primitives, but it will be a fair bit longer. More importantly, using the parallel stream is only safe if the function f
is a pure function. Pure functions are much more the norm in Scala than they are in Java. As such, it is much more likely that you will be able to take existing functions in Scala and use them in parallel than you will be able to in Java.
I feel that Futures provide an even better example, because they illustrate the power of the Scala syntax to make DSLs, something that Java clearly lacks.
val futures = for(v <- values) yield Future { f(v) }
val resultF = Future.sequence(futures).map(_.sum)
This code does the same thing as the parallel collection, but it does it in a way that could be used to do far more interesting things. Because it does the same thing, the issue with the nature of f
remains, but what stands out to me in this example is the ease of expressing the creation and use of Futures. I know that there are people on these boards who dislike the pass-by-name semantics in Scala, but I think they are wonderful for the creation of DSL features like Future. This code would make a lot of people think that Future is a language construct because of the Future { ... }
syntax, but as has been pointed out in this thread, no parallel constructs are built into the Scala language. It is just that the language is flexible enough to make libraries that look like language constructs. To my mind, this isn’t just a convenience, it is something that boosts productivity.
To see this, just take the two examples above and convert them to Java using parallel streams and completable futures. For fun, assume that values
starts its life as an array, then some refactoring changes it to a List and see how the code has to be modified. Also think about your code base and how often elements in the Java code have side effects, especially mutation, and what it would take to get rid of that to make it so that it was safer to reuse existing code in parallel contexts. If the code were written in Scala, odds are good that the code style would be largely functional with a heavy use of val and immutable collections. Most of your functions would be pure functions, and would, therefore, be safe to use in a parallel context.
The thing about parallelism is that it is really a project-wide concern and it goes way beyond just performance issues. So if you have a team of highly qualified Java developers who are always diligent and don’t mind writing more verbose code, then they can probably do just as well in Java as in Scala. However, standard Scala style will produce code that is both shorter and less error-prone, so I expect most real teams will get more done using Scala.