Use of threadlocalrandom in Java

Use of threadlocalrandom in Java

In Java, we usually need to use Java util. Random to facilitate the production of random numbers. However, random is thread safe. If it is used in a threaded environment, it may cause performance bottlenecks.

Let's take the nextint method commonly used in random as an example:

    public int nextInt() {
        return next(32);
    }

The nextint method actually calls the following method:

    protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

From the code, we can see that atomiclong is used inside the method and its compareandset method is called to ensure thread safety. So this is a thread safe method.

In fact, in a multi-threaded environment, random simply needs to share instances. What should I do?

A threadlocalrandom class is introduced in JDK 7. As we all know, ThreadLocal is the local variable of the thread, and threadlocalrandom is the local random of the thread.

Let's see how to call:

ThreadLocalRandom.current().nextInt();

Let's write a benchmark test for these two classes:

public class RandomUsage {

    public void testRandom() throws InterruptedException {
        ExecutorService executorService=Executors.newFixedThreadPool(2);
        Random random = new Random();
        List<Callable<Integer>> callables = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            callables.add(() -> {
                return random.nextInt();
            });
            }
        executorService.invokeAll(callables);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(RandomUsage.class.getSimpleName())
                // 预热5轮
                .warmupIterations(5)
                // 度量10轮
                .measurementIterations(10)
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}
public class ThreadLocalRandomUsage {

    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    public void testThreadLocalRandom() throws InterruptedException {
        ExecutorService executorService=Executors.newFixedThreadPool(2);
        List<Callable<Integer>> callables = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            callables.add(() -> {
                return ThreadLocalRandom.current().nextInt();
            });
            }
        executorService.invokeAll(callables);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(ThreadLocalRandomUsage.class.getSimpleName())
                // 预热5轮
                .warmupIterations(5)
                // 度量10轮
                .measurementIterations(10)
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}

By analyzing the running results, we can see that threadlocalrandom is faster than random in a multithreaded environment.

Examples of this article can be referred to https://github.com/ddean2009/learn-java-concurrency/tree/master/ThreadLocalRandom

For updated articles, please refer to flydean's blog

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>