Getting legacy pseudo-random generator from new ones of JDK 17 – Text blocks, Locales, Numbers & Math
By Adenike Adekola / August 26, 2022 / No Comments / Exams of Java, Filling a long array with pseudo-random numbers, Getting integral and fractional parts from a double, Java Certifications
32. Getting legacy pseudo-random generator from new ones of JDK 17
A legacy pseudo-random generator such as Random, SecureRandom, or ThreadLocalRandom can delegate method calls to a RandomGenerator passed as an argument to Random.from(), SecureRandom.from(), or ThreadLocalRandom.from() as follows:
Random legacyRnd = Random.from(
RandomGenerator.of(“L128X256MixRandom”));
// or, like his
Random legacyRnd = Random.from(RandomGeneratorFactory.
of(“Xoroshiro128PlusPlus”).create());
// or, like this
Random legacyRnd = Random.from(RandomGeneratorFactory
.<RandomGenerator.SplittableGenerator>of(
“L128X256MixRandom”).create());
The from() methods are available starting with JDK 19. In the bundled code you can see more examples.
33. Using pseudo-random generators in a thread-safe fashion (multithreaded environments)
Random and SecureRandom instances are thread-safe. While this statement is true, pay attention that when a Random instance (or Math.random()) is used by multiple threads (multithreaded environment) your code is prone to thread contention because these threads share the same seed. Sharing the same seed involves synchronization of the seed access therefore it opens a gate to thread contention. Obviously, thread contention leads to performance penalties since threads may wait in the queue to gain access to the seed. Synchronization is typically expensive.An alternative to Random is ThreadLocalRandom which uses a Random instance for each thread and provides protection against thread contention since it doesn’t contain synchronized code or atomic operations. The downside is that ThreadLocalRandom uses an internal seed per thread that we cannot control or modify.SplittableRandom is not thread-safe. Moreover, the new API consisting of implementations of RandomGenerator is not thread-safe.This being said, a pseudo-random generator can be used in a multithread environment by using a thread-safe generator or by splitting a new instance for each new thread. And when I say “splitting” I mean to use SplittableGenerator.splits(long n), where n is the number of splits. Check out the code that uses 10 threads to populate with integers a Java list (each thread uses its own pseudo-random generator):
List<Integer> listOfInts = new CopyOnWriteArrayList<>();
ExecutorService executorService
= Executors.newCachedThreadPool();
SplittableGenerator splittableGenerator
= RandomGeneratorFactory
.<SplittableGenerator>of(“L128X256MixRandom”).create();
splittableGenerator.splits(10)
.forEach((anotherSplittableGenerator) -> {
executorService.submit(() -> {
int nextInt = anotherSplittableGenerator.nextInt(1_000);
logger.info(() -> “Added in list “
+ nextInt + ” by generator “
+ anotherSplittableGenerator.hashCode()
+ ” running in thread”
+ Thread.currentThread().getName());
listOfInts.add(nextInt);
});
});
shutdownExecutor(executorService);
A snippet from the output:
INFO: Added in list 192 by generator 1420516714 running in threadpool-1-thread-3
INFO: Added in list 366 by generator 1190794841 running in threadpool-1-thread-8
INFO: Added in list 319 by generator 275244369 running in threadpool-1-thread-9
…
You can also use a JumpableGenerator or LeapableGenerator. Only that instead of splits(), JumpableGenerator uses jumps() and LeapableGenerator uses leaps().It is time to summarize this chapter and move forward.
Summary
This chapter collected 33 problems related to strings, locales, numbers, and math meant to mix classical must-know problems with a bunch of problems solved via the latest JDK features such as text blocks and pseudo-random generators. If you want to solve even more such problems then consider Java Coding Problems, First Edition, which has a similar chapter (Chapter 1) covering 39 problems.