In normal development, we often use random numbers, such as using new Random()
, Math.random()
etc., but in high-concurrency environments (such as e-commerce projects, middleware systems, etc.) using the above methods is not optimal and will affect system performance . So how can we generate random numbers in a high-concurrency environment?
Use Random to generate random numbers
@Test
public void testRandom() {
for (int i = 0; i < 10; i++) {
double random = Math.random();
System.out.println(random);
}
}
Test Results:
0.5036752695751798
0.6386142116701573
0.9884333194038111
0.9582700780194423
0.5868131855429274
0.4641415198964046
0.003620726435900945
0.3840115367892679
0.5840416616384468
0.2752130416815357
Random's source code:
public static double random() {
return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
private static final class RandomNumberGeneratorHolder {
static final Random randomNumberGenerator = new Random();
}
CAS is used in the bottom layer
For a thread to obtain a new random number, it needs to do two things:
“”
Generate a new seed based on the old seed
Generate random numbers from the new seed
In multi-threading, in order to prevent each thread from getting the same seed
, Random
use the AtomicLong CAS
(compare and set) operation to update it seed
. We look at the above code, if the thread CAS fails, it will spin here (retry in a loop). So here is the competition between multiple threads on the seed. Occupies system resources.
Use ThreadLocalRandom to generate random numbers
Use the java.util.concurrent
following to ThreadLocalRandom
generate random numbers under high concurrency :
public static void main(String[] args){
new RandomTest().testThreadLocalRandom();
}
public void testThreadLocalRandom() {
for (int i = 0; i < 3 ; i++) {
new Thread(() -> System.out
.println(Thread.currentThread().getName() + ": " +
ThreadLocalRandom.current().nextDouble())).start();
}
}
Java code test results:
Thread-0: 0.24025397109614877
Thread-2: 0.1704942948906747
Thread-1: 0.6864282829219596
Let's look at the ThreadLocalRandom.current()
method:
current()
The method is a static method, so multiple threads will only generate one ThreadLocalRandom
实例
.
random number
When we call the current()
method, if the current thread is not initialized, it will be initialized seed
(called localInit()
) first , and the current thread information and corresponding information will be seed
saved in UNSAFE
it. UNSAFE
The methods are all local methods, and the methods that are related to the operating system are called, so we won't go into it here.
Note here that we have to call in each thread ThreadLocalRandom.current()
.
We found that TheadLocalRandom
CAS was not used. This is why the random number generated by it is fast.
Use TheadLocalRandom
, each thread will maintain its own seed
, so there is no situation where multiple threads compete for the same seed resource.
TheadLocalRandom
The performance tested by someone on the Internet is 8-10 times faster than Random.
So in the case of high concurrency, use ThreadLocalRandom
random number generation.
Recommended in the past
Scan the QR code to get more exciting. Or search Lvshen_9 on WeChat , you can reply to get information in the background
回复"java" 获取java电子书;
回复"python"获取python电子书;
回复"算法"获取算法电子书;
回复"大数据"获取大数据电子书;
回复"spring"获取SpringBoot的学习视频。
回复"面试"获取一线大厂面试资料
回复"进阶之路"获取Java进阶之路的思维导图
回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)
回复"总结"获取Java后端面试经验总结PDF版
回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)
回复"并发导图"获取Java并发编程思维导图(xmind终极版)
Another: Click [ My Benefits ] to have more surprises.