diff --git a/core-java-modules/core-java-17/pom.xml b/core-java-modules/core-java-17/pom.xml
index 2fe16cad57..bc949d9050 100644
--- a/core-java-modules/core-java-17/pom.xml
+++ b/core-java-modules/core-java-17/pom.xml
@@ -27,6 +27,13 @@
--enable-preview
${maven.compiler.source.version}
${maven.compiler.target.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh-generator.version}
+
+
@@ -49,6 +56,20 @@
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh-core.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh-generator.version}
+ test
+
+
+
17
17
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/BenchmarkRunner.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/BenchmarkRunner.java
new file mode 100644
index 0000000000..9a40a2de4e
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/BenchmarkRunner.java
@@ -0,0 +1,115 @@
+package com.baeldung.randomgenerators;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+
+import java.util.concurrent.TimeUnit;
+import java.util.random.RandomGenerator;
+
+public class BenchmarkRunner {
+
+ public static void main(String[] args) throws Exception {
+ org.openjdk.jmh.Main.main(args);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL128X1024MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L128X1024MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL128X128MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L128X128MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL128X256MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L128X256MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL32X64MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L32X64MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL64X1024MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L64X1024MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL64X128MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L64X128MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL64X128StarStarRandom() {
+ generateRandomNumbers(RandomGenerator.of("L64X128StarStarRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testL64X256MixRandom() {
+ generateRandomNumbers(RandomGenerator.of("L64X256MixRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testRandom() {
+ generateRandomNumbers(RandomGenerator.of("Random"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testSecureRandom() {
+ generateRandomNumbers(RandomGenerator.of("SecureRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testSplittableRandom() {
+ generateRandomNumbers(RandomGenerator.of("SplittableRandom"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testXoroshiro128PlusPlus() {
+ generateRandomNumbers(RandomGenerator.of("Xoroshiro128PlusPlus"));
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public static void testXoshiro256PlusPlus() {
+ generateRandomNumbers(RandomGenerator.of("Xoshiro256PlusPlus"));
+ }
+
+ private static void generateRandomNumbers(RandomGenerator generator) {
+ generator.nextLong();
+ generator.nextInt();
+ generator.nextFloat();
+ generator.nextDouble();
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/GeneratorFactory.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/GeneratorFactory.java
new file mode 100644
index 0000000000..64bc81a035
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/GeneratorFactory.java
@@ -0,0 +1,36 @@
+package com.baeldung.randomgenerators;
+
+import java.util.Comparator;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGeneratorFactory;
+
+public class GeneratorFactory {
+
+ public static void main(String[] args) {
+ System.out.println("Group\tName\tJumpable?\tSplittable?");
+ RandomGeneratorFactory.all()
+ .sorted(Comparator.comparing(RandomGeneratorFactory::name))
+ .forEach(factory -> System.out.println(String.format("%s\t%s\t%s\t%s",
+ factory.group(),
+ factory.name(),
+ factory.isJumpable(),
+ factory.isSplittable())));
+ }
+
+ public static int getRandomInt(RandomGenerator generator, int bound) {
+ return generator.nextInt(bound);
+ }
+
+ public static RandomGenerator getDefaultGenerator() {
+ return RandomGeneratorFactory.getDefault().create();
+ }
+
+ public static RandomGenerator getJumpableGenerator() {
+ return RandomGeneratorFactory.all()
+ .filter(RandomGeneratorFactory::isJumpable)
+ .findAny()
+ .map(RandomGeneratorFactory::create)
+ .orElseThrow(() -> new RuntimeException("Error creating a generator"));
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/OldRandom.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/OldRandom.java
new file mode 100644
index 0000000000..c84d5bc8d3
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/OldRandom.java
@@ -0,0 +1,12 @@
+package com.baeldung.randomgenerators;
+
+import java.util.Random;
+
+public class OldRandom {
+
+ public static int getRandomInt(int bound) {
+ Random random = new Random();
+ return random.nextInt(bound);
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThread.java b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThread.java
new file mode 100644
index 0000000000..298d840da9
--- /dev/null
+++ b/core-java-modules/core-java-17/src/main/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThread.java
@@ -0,0 +1,30 @@
+package com.baeldung.randomgenerators;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.random.RandomGenerator;
+import java.util.random.RandomGeneratorFactory;
+
+public class SplittableGeneratorMultiThread {
+
+ public static List generateNumbersInMultipleThreads() {
+ List numbers = Collections.synchronizedList(new ArrayList<>());
+ ExecutorService executorService = Executors.newCachedThreadPool();
+
+ RandomGenerator.SplittableGenerator sourceGenerator = RandomGeneratorFactory
+ .of("L128X256MixRandom")
+ .create();
+
+ sourceGenerator.splits(20).forEach((splitGenerator) -> {
+ executorService.submit(() -> {
+ numbers.add(splitGenerator.nextInt(10));
+ });
+ });
+
+ return numbers;
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/main/java/module-info.java b/core-java-modules/core-java-17/src/main/java/module-info.java
index b1ce62aa68..319678832e 100644
--- a/core-java-modules/core-java-17/src/main/java/module-info.java
+++ b/core-java-modules/core-java-17/src/main/java/module-info.java
@@ -1,4 +1,7 @@
module core.java {
requires jdk.incubator.vector;
requires jdk.incubator.foreign;
+ requires jmh.core;
+ requires jdk.unsupported;
+ exports com.baeldung.randomgenerators.jmh_generated;
}
\ No newline at end of file
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorFactoryUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorFactoryUnitTest.java
new file mode 100644
index 0000000000..b009b4eeb0
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorFactoryUnitTest.java
@@ -0,0 +1,21 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class GeneratorFactoryUnitTest {
+
+ @Test
+ void givenDefaultGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+ int number = GeneratorFactory.getRandomInt(GeneratorFactory.getDefaultGenerator(), 10);
+ assertThat(number).isNotNegative().isLessThan(10);
+ }
+
+ @Test
+ void givenJumpableGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+ int number = GeneratorFactory.getRandomInt(GeneratorFactory.getJumpableGenerator(), 10);
+ assertThat(number).isNotNegative().isLessThan(10);
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorSelectionUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorSelectionUnitTest.java
new file mode 100644
index 0000000000..0732c3f54e
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/GeneratorSelectionUnitTest.java
@@ -0,0 +1,25 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.random.RandomGenerator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class GeneratorSelectionUnitTest {
+
+ @Test
+ void givenDefaultGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+ RandomGenerator generator = RandomGenerator.getDefault();
+ int number = generator.nextInt(10);
+ assertThat(number).isNotNegative().isLessThan(10);
+ }
+
+ @Test
+ void givenSpecificGenerator_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+ RandomGenerator generator = RandomGenerator.of("L128X256MixRandom");
+ int number = generator.nextInt(10);
+ assertThat(number).isNotNegative().isLessThan(10);
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/OldRandomUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/OldRandomUnitTest.java
new file mode 100644
index 0000000000..4a18369686
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/OldRandomUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class OldRandomUnitTest {
+
+ @Test
+ void givenOldRandomApi_whenGeneratingAnInt_thenIntInRangeIsGenerated() {
+ int number = OldRandom.getRandomInt(10);
+ assertThat(number).isNotNegative().isLessThan(10);
+ }
+
+}
diff --git a/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThreadUnitTest.java b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThreadUnitTest.java
new file mode 100644
index 0000000000..ba4cd8eb2b
--- /dev/null
+++ b/core-java-modules/core-java-17/src/test/java/com/baeldung/randomgenerators/SplittableGeneratorMultiThreadUnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.randomgenerators;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class SplittableGeneratorMultiThreadUnitTest {
+
+ @Test
+ void givenSplittableGenerator_whenUsingMultipleThreads_thenListOfIntsIsGenerated() {
+ List numbers = SplittableGeneratorMultiThread.generateNumbersInMultipleThreads();
+ assertThat(numbers).hasSize(20).allMatch(number -> number >= 0 && number <= 10);
+ }
+
+}