How to generate random numbers under high concurrency

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

image

For a thread to obtain a new random number, it needs to do two things:

  1. Generate a new seed based on the old seed

  2. Generate random numbers from the new seed

image

In multi-threading, in order to prevent each thread from getting the same seed, Randomuse 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.concurrentfollowing to ThreadLocalRandomgenerate 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:

image

current()The method is a static method, so multiple threads will only generate one ThreadLocalRandom实例.

image

random number

image

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 seedsaved in UNSAFEit. UNSAFEThe 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().

image

We found that TheadLocalRandomCAS 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.

TheadLocalRandomThe performance tested by someone on the Internet is 8-10 times faster than Random.

So in the case of high concurrency, use ThreadLocalRandomrandom 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

  1. 回复"java" 获取java电子书;

  2. 回复"python"获取python电子书;

  3. 回复"算法"获取算法电子书;

  4. 回复"大数据"获取大数据电子书;

  5. 回复"spring"获取SpringBoot的学习视频。

  6. 回复"面试"获取一线大厂面试资料

  7. 回复"进阶之路"获取Java进阶之路的思维导图

  8. 回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)

  9. 回复"总结"获取Java后端面试经验总结PDF版

  10. 回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)

  11. 回复"并发导图"获取Java并发编程思维导图(xmind终极版)

Another: Click [ My Benefits ] to have more surprises.

Guess you like

Origin blog.csdn.net/wujialv/article/details/111879670