JDK-6937857 : Concurrent calls to new Random() not random enough
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.concurrent
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-03-24
  • Updated: 2015-02-04
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b94Fixed
Related Reports
Relates :  
Description
new Random() promises this:
    /**
     * Creates a new random number generator. This constructor sets
     * the seed of the random number generator to a value very likely
     * to be distinct from any other invocation of this constructor.
     */

but if there are concurrent calls to new Random(), it does not
do very well at fulfilling its contract.

The following program should print out a number much closer to 0.

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;

public class RandomSeedCollisions {
    public static void main(String[] args) throws Throwable {
        class RandomCollector implements Runnable {
            long[] randoms = new long[1<<16];
            public void run() {
                for (int i = 0; i < randoms.length; i++)
                    randoms[i] = new Random().nextLong();
            }};
        final int threadCount = 2;
        List<RandomCollector> collectors = new ArrayList<RandomCollector>();
        List<Thread> threads = new ArrayList<Thread>();
        for (int i = 0; i < threadCount; i++) {
            RandomCollector r = new RandomCollector();
            collectors.add(r);
            threads.add(new Thread(r));
        }
        for (Thread thread : threads)
            thread.start();
        for (Thread thread : threads)
            thread.join();
        int collisions = 0;
        HashSet<Long> s = new HashSet<Long>();
        for (RandomCollector r : collectors) {
            for (long x : r.randoms) {
                if (s.contains(x))
                    collisions++;
                s.add(x);
            }
        }
        System.out.printf("collisions=%d%n", collisions);
        if (collisions > 10)
            throw new Error("too many collisions");
    }
}

Comments
EVALUATION Martin has pushed this to tl/jdk: http://hg.openjdk.java.net/jdk7/tl/jdk/rev/df4d3e3e465a
2010-05-11