10

Java 8 added a random number generator called SplittableRandom which seems to be meant for use with streams. However, it isn't clear how it is better than or more useful than ThreadLocalRandom. From reading documentation, it seems the algorithm was changed to have better statistical properties. That said, why not call it BetterThreadLocalRandom and drop the split method? Why would anyone ever call split()?

Carl Mastrangelo
  • 5,970
  • 1
  • 28
  • 37
  • `BetterThreadLocalRandom` lol – Jorge Campos Nov 28 '17 at 02:38
  • Considering that it isn't, and isn't supposed to be, a drop-in replacement for `ThreadLocalRandom`, calling it something like `BetterThreadLocalRandom` would be misleading. It's not even thread-local. – user2357112 Nov 28 '17 at 02:40
  • I have an even better class and I am calling it `TheBestEverThreadLocalRandom` – Scary Wombat Nov 28 '17 at 02:41
  • The question is more at: why is SplittableRandom, a class that can split randoms, needed? The criticisms of ThreadLocalRandom seem to be about its implementation, not its API. – Carl Mastrangelo Nov 28 '17 at 02:46

2 Answers2

13

The usefulness of SplittableRandom comes from being a deterministic random number generator. In the case of streams, different threads may use different ThreadLocalRandom values, leading to different calculations each time. Doug Lea mentions this in passing while introducing the class:

"While the ThreadLocalRandom option is great for many purposes, you wouldn't want to use it in, say, a high-quality Monte Carlo simulation."

If there is an interesting outcome to a simulation, and it depended upon a particular sequence of random numbers, SplittableRandom let's you repeat it for further analysis.

Carl Mastrangelo
  • 5,970
  • 1
  • 28
  • 37
  • Can't the normal `Random` do that too? I thought the point of `SplittableRandom` was that each instance produces statistically independent streams from any other instance, which other implementations do not guarantee. I only wonder why not just replace the implementation of `Random` instead... – kaqqao Jan 24 '19 at 21:09
  • 1
    Normal random can do that, but it pays synchronization costs in the `next()` function, unlike SplittableRandom. – Carl Mastrangelo Jan 24 '19 at 23:18
1

You are comparing two different things meant to be used in different situations. One can fulfil the role of the other up to a certain extent.

A ThreadLocalRandom is just an instance of a random generator different for the local thread, a SplittableRandom is a generator and even a generator of generators since it can be split recursively and provide a new SplittableRandom.

But a SplittableRandom has nothing to do with threads since it is meant to provide something able to cooperate friendly with streams in a functional environment.

Providing random data should be thread agnostic, even using parallel() on streams should be thread agnostic. I wouldn't like to find myself doing ThreadLocalRandom.current() inside a lambda that is processing a stream, would you?

In addition, an implementation which uses a fixed sized pool of sleeping/waking threads to process a parallel stream would use the same ThreadLocalRandom for multiple entries, this couldn't happen with a SplittableRandom which is bound to a possible parallel path of processing, not to a specific thread.

Bax
  • 4,260
  • 5
  • 43
  • 65
Jack
  • 131,802
  • 30
  • 241
  • 343
  • 1
    Yes I would use ThreadLocalRandom in a stream, why wouldn't I? Of course wouldn't pass around the instance itself, but why is there anything wrong with making that invocation? – Carl Mastrangelo Nov 28 '17 at 02:51
  • @CarlMastrangelo: because you don't even know which thread is executing a lambda used in a stream for a specific entry, what if you have only one thread? What if you have a fixed amount of threads? A `SplittableRandom` provides an infinite random spawning mechanics, which is what I'd expect in a functional environment. – Jack Nov 28 '17 at 02:55
  • Why does the number of threads matter at all? If there is only one thread, then each call to TLR.current().next() is going to return an unpredictable number. What more can SplittableRandom provide? I was hoping to see a piece of code where using TLR would be incorrect. – Carl Mastrangelo Nov 28 '17 at 02:58
  • It's a matter of design philosophy, have you ever used a functional only programming language as OCaml or Haskell? The only idea of calling a static method which returns a static object to manage generation of random data is not a good design in a functional environment. That's why a `SplittableRandom`, which is not static, which provides an infinite amount of streams of random data is definitely a better way. – Jack Nov 28 '17 at 03:09
  • TLR has a lot of objective benefits that SR doesn't seem to provide: It's threadsafe, it has zero contention, and it doesn't allocate memory. You mention streams of random numbers; how is one stream different from another? They are all unpredictable numbers, which is what TLR provides. You couldn't distinguish between the streams of SR numbers and those produced by TLR. There don't seem to be any usecases where SR would produce better random numbers or be faster. It doesn't even simplify the code. – Carl Mastrangelo Nov 28 '17 at 03:16