/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.math4.random; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.apache.commons.rng.simple.RandomSource; import org.junit.Assert; import org.junit.Test; public class SynchronizedRandomGeneratorTest { private final int numberOfThreads = 5; private final int numberOfGenerators = 5; private final int numberOfSamples = 100000; @Test public void testAdapter() { final int seed = 12345; final RandomGenerator orig = new RngAdaptor(RandomSource.MT, seed); final RandomGenerator wrap = new SynchronizedRandomGenerator(new RngAdaptor(RandomSource.MT, seed)); final int bSize = 67; final byte[] bOrig = new byte[bSize]; final byte[] bWrap = new byte[bSize]; for (int i = 0; i < 100; i++) { orig.nextBytes(bOrig); wrap.nextBytes(bWrap); for (int k = 0; k < bSize; k++) { Assert.assertEquals(bOrig[k], bWrap[k]); } Assert.assertEquals(orig.nextInt(), wrap.nextInt()); final int range = (i + 1) * 89; Assert.assertEquals(orig.nextInt(range), wrap.nextInt(range)); Assert.assertEquals(orig.nextLong(), wrap.nextLong()); Assert.assertEquals(orig.nextBoolean(), wrap.nextBoolean()); Assert.assertEquals(orig.nextFloat(), wrap.nextFloat(), 0); Assert.assertEquals(orig.nextDouble(), wrap.nextDouble(), 0); Assert.assertEquals(orig.nextGaussian(), wrap.nextGaussian(), 0); } } @Test public void testMath899Sync() throws Throwable { try { // Running the test several times in order to decrease the // probability that a non-thread-safe code did not trigger // a concurrency problem. for (int i = 0; i < 10; i++) { doTestMath899(true, numberOfThreads, numberOfGenerators, numberOfSamples); } } catch (InterruptedException e) { Assert.fail(e.getMessage()); } catch (ExecutionException e) { throw e.getCause(); } } /** * @param sync Whether to use a synchronizing wrapper. */ private double[] doTestMath899(final boolean sync, final int numThreads, final int numGenerators, final int numSamples) throws InterruptedException, ExecutionException { final RandomGenerator rng = new RngAdaptor(RandomSource.MT); final RandomGenerator wrapper = sync ? new SynchronizedRandomGenerator(rng) : rng; final List<Callable<Double>> tasks = new ArrayList<>(); for (int i = 0; i < numGenerators; i++) { tasks.add(new Callable<Double>() { @Override public Double call() { Double lastValue = 0d; for (int j = 0; j < numSamples; j++) { lastValue = wrapper.nextGaussian(); } return lastValue; } }); } final ExecutorService exec = Executors.newFixedThreadPool(numThreads); final List<Future<Double>> results = exec.invokeAll(tasks); final double[] values = new double[numGenerators]; for (int i = 0; i < numGenerators; i++) { values[i] = results.get(i).get(); } return values; } }