Hem » Java » Generating pseudorandom numbers in Java

Generating pseudorandom numbers in Java


I had a closer look at generating pseudorandom numbers in Java the other day. Mainly nailing the difference between using Math,random, new Random() or (since Java 7) ThreadLocalRandom. Enjoy the little example, (and if i did something wrong, please correct me in the comments).


package com.funstuff.javapractices.commontasks;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Examples of different ways to run random.
 *
 * This shows 3 different ways of generating a basic pseudorandomnumber in
 * Java.
 *
 * 

* Using: Math.random, new Random and ThreadLocalRandom * *

* Math.random uses Random.nextDouble() underneath the hood; Random.nextDouble * is not as efficient as for example Random.nextInt * http://stackoverflow.com/questions/738629/math-random-versus-random-nextintint * * Math.random() uses a single static java.util.Random instance, which itself is * thread-safe? This can generate contention- if you have multiple threads * that are supposed to run in parallel, through Math.random() they will all * compete for its lock and can deteriorate into running serially. * *

* The Random object has different utility methods, and by default gets it's * seed from the systemtime. It has constructor that let's you set your own * seed. As this is pseudorandom algorithms - If you initialize multiple Random * objects with the same seed they'll generate the same numbersequence. * *

* * From the javadocs: "the concurrent use of the same java.util.Random * instance across threads may encounter contention and consequent poor * performance. Consider instead using ThreadLocalRandom in multithreaded * designs." * * With java 7 comes ThreadLocalRandom in the java.util.concurrency package * (wich extends java.util.Random) Characteristics is that it prohibits setSeed * (gives UnsupportedOperationException), it's static and it's threadlocal. And while * Math.random() works on a static singleton instance of Random, * ThreadLocalRandom works on a thread local instance. See * http://niklasschlimm.blogspot.se/2012/01/java-7-how-to-write-really-fast-java.html * for a good and deep explanation. * * * * * @author whatever whatever */ public final class RandomNumbers { private static int loopCtr = 10000; private static long startTime; private static long endTime; public static void main(String... args) { System.out.println(System.lineSeparator()); mathRandom(); newRandom(); threadLocalRandom(); System.out.println(System.lineSeparator()); //raise the stakes.. loopCtr = 1600000; mathRandom(); newRandom(); threadLocalRandom(); System.out.println(System.lineSeparator()); //just a range example newRandomWithRange(); } private static void mathRandom() { startTime = System.currentTimeMillis(); for (int i = 0; i < loopCtr; i++) { ////gives a double between 0.0 and less than 1.0 //but often seen used like this ( here to give a number between 1 and 10) long mathRandomDoubleRounded = Math.round(Math.random() * 10); } endTime = System.currentTimeMillis(); System.out.println("Total execution time: " + (endTime - startTime) + "ms"); } private static void newRandom() { startTime = System.currentTimeMillis(); Random random = new Random(); for (int i = 0; i < loopCtr; i++) { double randomDouble = random.nextDouble(); } endTime = System.currentTimeMillis(); System.out.println("Total execution time: " + (endTime - startTime) + "ms"); } private static void newRandomWithRange() { //random x between 0 and less than 11 - (Remember Java usually handles ranges like [inclusive, exclusive]) //and to get a range, just add the MIN of your range .i.e //we want something between 10 and 17, and init with (MAX-MIN)+1 int min = 10; int max = 17; Random random = new Random(); int randomValue = (random.nextInt((max - min) + 1) + min); System.out.println("RandomValue:" + randomValue); } private static void threadLocalRandom() { startTime = System.currentTimeMillis(); for (int i = 0; i < loopCtr; i++) { double threadLocalRandom = ThreadLocalRandom.current().nextDouble(); } endTime = System.currentTimeMillis(); System.out.println("Total execution time: " + (endTime - startTime) + "ms"); } }

See this blog for digging deeper!.

Lämna en kommentar