View | Details | Raw Unified | Return to bug 54453
Collapse All | Expand All

(-)src/functions/org/apache/jmeter/functions/Random.java (-3 / +7 lines)
Lines 36-42 Link Here
36
public class Random extends AbstractFunction {
36
public class Random extends AbstractFunction {
37
37
38
    private static final List<String> desc = new LinkedList<String>();
38
    private static final List<String> desc = new LinkedList<String>();
39
39
    private static final boolean USE_THREAD_LOCAL_RANDOM = JMeterUtils.getPropDefault("use.threadlocalrandom", false);
40
    private static final String KEY = "__Random"; //$NON-NLS-1$
40
    private static final String KEY = "__Random"; //$NON-NLS-1$
41
41
42
    static {
42
    static {
Lines 62-69 Link Here
62
        long min = Long.parseLong(minimum.execute().trim());
62
        long min = Long.parseLong(minimum.execute().trim());
63
        long max = Long.parseLong(maximum.execute().trim());
63
        long max = Long.parseLong(maximum.execute().trim());
64
64
65
        long rand = min + (long) (Math.random() * (max - min + 1));
65
        long rand = 0;
66
66
        if(USE_THREAD_LOCAL_RANDOM) {
67
            rand = min + (ThreadLocalRandom.current().nextLong(max - min + 1));
68
        } else {
69
            rand = min + (long) (Math.random() * (max - min + 1));
70
        }
67
        String randString = Long.toString(rand);
71
        String randString = Long.toString(rand);
68
72
69
        if (varName != null) {
73
        if (varName != null) {
(-)src/functions/org/apache/jmeter/functions/ThreadLocalRandom.java (+202 lines)
Line 0 Link Here
1
/*
2
 * Written by Doug Lea with assistance from members of JCP JSR-166
3
 * Expert Group and released to the public domain, as explained at
4
 * http://creativecommons.org/publicdomain/zero/1.0/
5
 */
6
7
// This is based on 1.16 version
8
9
package org.apache.jmeter.functions;
10
11
import java.util.Random;
12
13
/**
14
 * A random number generator isolated to the current thread.  Like the
15
 * global {@link java.util.Random} generator used by the {@link
16
 * java.lang.Math} class, a {@code ThreadLocalRandom} is initialized
17
 * with an internally generated seed that may not otherwise be
18
 * modified. When applicable, use of {@code ThreadLocalRandom} rather
19
 * than shared {@code Random} objects in concurrent programs will
20
 * typically encounter much less overhead and contention.  Use of
21
 * {@code ThreadLocalRandom} is particularly appropriate when multiple
22
 * tasks (for example, each a {@link ForkJoinTask}) use random numbers
23
 * in parallel in thread pools.
24
 *
25
 * <p>Usages of this class should typically be of the form:
26
 * {@code ThreadLocalRandom.current().nextX(...)} (where
27
 * {@code X} is {@code Int}, {@code Long}, etc).
28
 * When all usages are of this form, it is never possible to
29
 * accidently share a {@code ThreadLocalRandom} across multiple threads.
30
 *
31
 * <p>This class also provides additional commonly used bounded random
32
 * generation methods.
33
 *
34
 * @since 1.7
35
 * @author Doug Lea
36
 */
37
public class ThreadLocalRandom extends Random {
38
    // same constants as Random, but must be redeclared because private
39
    private static final long multiplier = 0x5DEECE66DL;
40
    private static final long addend = 0xBL;
41
    private static final long mask = (1L << 48) - 1;
42
43
    /**
44
     * The random seed. We can't use super.seed.
45
     */
46
    private long rnd;
47
48
    /**
49
     * Initialization flag to permit calls to setSeed to succeed only
50
     * while executing the Random constructor.  We can't allow others
51
     * since it would cause setting seed in one part of a program to
52
     * unintentionally impact other usages by the thread.
53
     */
54
    boolean initialized;
55
56
    // Padding to help avoid memory contention among seed updates in
57
    // different TLRs in the common case that they are located near
58
    // each other.
59
    private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
60
61
    /**
62
     * The actual ThreadLocal
63
     */
64
    private static final ThreadLocal<ThreadLocalRandom> localRandom =
65
        new ThreadLocal<ThreadLocalRandom>() {
66
            @Override
67
            protected ThreadLocalRandom initialValue() {
68
                return new ThreadLocalRandom();
69
            }
70
    };
71
72
73
    /**
74
     * Constructor called only by localRandom.initialValue.
75
     */
76
    ThreadLocalRandom() {
77
        super();
78
        initialized = true;
79
    }
80
81
    /**
82
     * Returns the current thread's {@code ThreadLocalRandom}.
83
     *
84
     * @return the current thread's {@code ThreadLocalRandom}
85
     */
86
    public static ThreadLocalRandom current() {
87
        return localRandom.get();
88
    }
89
90
    /**
91
     * Throws {@code UnsupportedOperationException}.  Setting seeds in
92
     * this generator is not supported.
93
     *
94
     * @throws UnsupportedOperationException always
95
     */
96
    @Override
97
    public void setSeed(long seed) {
98
        if (initialized)
99
            throw new UnsupportedOperationException();
100
        rnd = (seed ^ multiplier) & mask;
101
    }
102
103
    @Override
104
    protected int next(int bits) {
105
        rnd = (rnd * multiplier + addend) & mask;
106
        return (int) (rnd >>> (48-bits));
107
    }
108
109
    /**
110
     * Returns a pseudorandom, uniformly distributed value between the
111
     * given least value (inclusive) and bound (exclusive).
112
     *
113
     * @param least the least value returned
114
     * @param bound the upper bound (exclusive)
115
     * @throws IllegalArgumentException if least greater than or equal
116
     * to bound
117
     * @return the next value
118
     */
119
    public int nextInt(int least, int bound) {
120
        if (least >= bound)
121
            throw new IllegalArgumentException();
122
        return nextInt(bound - least) + least;
123
    }
124
125
    /**
126
     * Returns a pseudorandom, uniformly distributed value
127
     * between 0 (inclusive) and the specified value (exclusive).
128
     *
129
     * @param n the bound on the random number to be returned.  Must be
130
     *        positive.
131
     * @return the next value
132
     * @throws IllegalArgumentException if n is not positive
133
     */
134
    public long nextLong(long n) {
135
        if (n <= 0)
136
            throw new IllegalArgumentException("n must be positive");
137
        // Divide n by two until small enough for nextInt. On each
138
        // iteration (at most 31 of them but usually much less),
139
        // randomly choose both whether to include high bit in result
140
        // (offset) and whether to continue with the lower vs upper
141
        // half (which makes a difference only if odd).
142
        long offset = 0;
143
        while (n >= Integer.MAX_VALUE) {
144
            int bits = next(2);
145
            long half = n >>> 1;
146
            long nextn = ((bits & 2) == 0) ? half : n - half;
147
            if ((bits & 1) == 0)
148
                offset += n - nextn;
149
            n = nextn;
150
        }
151
        return offset + nextInt((int) n);
152
    }
153
154
    /**
155
     * Returns a pseudorandom, uniformly distributed value between the
156
     * given least value (inclusive) and bound (exclusive).
157
     *
158
     * @param least the least value returned
159
     * @param bound the upper bound (exclusive)
160
     * @return the next value
161
     * @throws IllegalArgumentException if least greater than or equal
162
     * to bound
163
     */
164
    public long nextLong(long least, long bound) {
165
        if (least >= bound)
166
            throw new IllegalArgumentException();
167
        return nextLong(bound - least) + least;
168
    }
169
170
    /**
171
     * Returns a pseudorandom, uniformly distributed {@code double} value
172
     * between 0 (inclusive) and the specified value (exclusive).
173
     *
174
     * @param n the bound on the random number to be returned.  Must be
175
     *        positive.
176
     * @return the next value
177
     * @throws IllegalArgumentException if n is not positive
178
     */
179
    public double nextDouble(double n) {
180
        if (n <= 0)
181
            throw new IllegalArgumentException("n must be positive");
182
        return nextDouble() * n;
183
    }
184
185
    /**
186
     * Returns a pseudorandom, uniformly distributed value between the
187
     * given least value (inclusive) and bound (exclusive).
188
     *
189
     * @param least the least value returned
190
     * @param bound the upper bound (exclusive)
191
     * @return the next value
192
     * @throws IllegalArgumentException if least greater than or equal
193
     * to bound
194
     */
195
    public double nextDouble(double least, double bound) {
196
        if (least >= bound)
197
            throw new IllegalArgumentException();
198
        return nextDouble() * (bound - least) + least;
199
    }
200
201
    private static final long serialVersionUID = -5851777807851030925L;
202
}

Return to bug 54453