最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java并發(fā)高的情況下用ThreadLocalRandom來生成隨機(jī)數(shù)

 更新時(shí)間:2022年05月15日 09:09:33   作者:麻雀也有明天TuT  
如果我們想要生成一個(gè)隨機(jī)數(shù),通常會(huì)使用Random類。但是在并發(fā)情況下Random生成隨機(jī)數(shù)的性能并不是很理想,本文主要介紹了java并發(fā)高的情況下用ThreadLocalRandom來生成隨機(jī)數(shù),感興趣的可以了解一下

一:簡述

如果我們想要生成一個(gè)隨機(jī)數(shù),通常會(huì)使用Random類。但是在并發(fā)情況下Random生成隨機(jī)數(shù)的性能并不是很理想,今天給大家介紹一下JUC包中的用于生成隨機(jī)數(shù)的類--ThreadLocalRandom.(本文基于JDK1.8)

二:Random的性能差在哪里

Random隨機(jī)數(shù)生成是和種子seed有關(guān),而為了保證線程安全性,Random通過CAS機(jī)制來保證線程安全性。從next()方法中我們可以發(fā)現(xiàn)seed是通過自旋鎖和CAS來進(jìn)行修改值的。如果在高并發(fā)的場景下,那么可能會(huì)導(dǎo)致CAS不斷失敗,從而導(dǎo)致不斷自旋,這樣就可能會(huì)導(dǎo)致服務(wù)器CPU過高。

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));
    }

三:ThreadLocalRandom的簡單使用

使用的方法很簡單,通過ThreadLocalRandom.current()獲取到ThreadLocalRandom實(shí)例,然后通過nextInt(),nextLong()等方法獲取一個(gè)隨機(jī)數(shù)。

代碼:

    @Test
    void test() throws InterruptedException {
        new Thread(()->{
            ThreadLocalRandom random = ThreadLocalRandom.current();
            System.out.println(random.nextInt(100));
        }).start();
        new Thread(()->{
            ThreadLocalRandom random = ThreadLocalRandom.current();
            System.out.println(random.nextInt(100));
        }).start();

        Thread.sleep(100);
    }

運(yùn)行結(jié)果:

四:為什么ThreadLocalRandom能在保證線程安全的情況下還能有不錯(cuò)的性能

我們可以看一下ThreadLocalRandom的代碼實(shí)現(xiàn)。

首先我們很容易看出這是一個(gè)餓漢式的單例

    /** Constructor used only for static singleton */
    private ThreadLocalRandom() {
        initialized = true; // false during super() call
    }

    /** The common ThreadLocalRandom */
    static final ThreadLocalRandom instance = new ThreadLocalRandom();

我們可以看到PROBE成員變量代表的是Thread類的threadLocalRandomProbe屬性的內(nèi)存偏移量,SEED成員變量代表的是Thread類的threadLocalRandomSeed屬性的內(nèi)存偏移量,SECONDARY成員變量代表的是Thread類的threadLocalRandomSecondarySeed屬性的內(nèi)存偏移量。

// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
static {
    try {
        UNSAFE = sun.misc.Unsafe.getUnsafe();
        Class<?> tk = Thread.class;
        SEED = UNSAFE.objectFieldOffset
            (tk.getDeclaredField("threadLocalRandomSeed"));
        PROBE = UNSAFE.objectFieldOffset
            (tk.getDeclaredField("threadLocalRandomProbe"));
        SECONDARY = UNSAFE.objectFieldOffset
            (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
    } catch (Exception e) {
        throw new Error(e);
    }
}

可以看到Thread類中確實(shí)有這三個(gè)屬性

Thread類:

    @sun.misc.Contended("tlr")
    //當(dāng)前Thread的隨機(jī)種子 默認(rèn)值是0
    long threadLocalRandomSeed;

    /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
    @sun.misc.Contended("tlr")
    //用來標(biāo)志當(dāng)前Thread的threadLocalRandomSeed是否進(jìn)行了初始化 0代表沒有,非0代表已經(jīng)初始化 默認(rèn)值是0
    int threadLocalRandomProbe;

    /** Secondary seed isolated from public ThreadLocalRandom sequence */
    @sun.misc.Contended("tlr")
    //當(dāng)前Thread的二級(jí)隨機(jī)種子 默認(rèn)值是0
    int threadLocalRandomSecondarySeed;

接下來我們看ThreadLocalRandom.current()方法。

ThreadLocalRandom.current()

ThreadLocalRandom.current()的作用主要是初始化隨機(jī)種子,并且返回ThreadLocalRandom的實(shí)例。

首先通過UNSAFE類獲取當(dāng)前線程的Thread對象的threadLocalRandomProbe屬性,看隨機(jī)種子是否已經(jīng)初始化。沒有初始化,那么調(diào)用localInit()方法進(jìn)行初始化

public static ThreadLocalRandom current() {
        // 獲取當(dāng)前線程的
        if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
            localInit();
        return instance;
    }

localInit()

localInit()方法的作用就是初始化隨機(jī)種子,可以看到代碼很簡單,就是通過UNSAFE類對當(dāng)前Thread的threadLocalRandomProbe屬性和threadLocalRandomSeed屬性進(jìn)行一個(gè)賦值。

static final void localInit() {
        int p = probeGenerator.addAndGet(PROBE_INCREMENT);
        int probe = (p == 0) ? 1 : p; // skip 0
        long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
        Thread t = Thread.currentThread();
        UNSAFE.putLong(t, SEED, seed);
        UNSAFE.putInt(t, PROBE, probe);
    }

接下來以nextInt()方法為例,看ThreadLocalRandom是如何生成到隨機(jī)數(shù)的。我們可以看出隨機(jī)數(shù)正是通過nextSeed()方法獲取到隨機(jī)種子,然后通過隨機(jī)種子而生成。所以重點(diǎn)看nextSeed()方法是如何獲取到隨機(jī)種子的。

public int nextInt(int bound) {
        if (bound <= 0)
            throw new IllegalArgumentException(BadBound);
        int r = mix32(nextSeed());
        int m = bound - 1;
        if ((bound & m) == 0) // power of two
            r &= m;
        else { // reject over-represented candidates
            for (int u = r >>> 1;
                 u + m - (r = u % bound) < 0;
                 u = mix32(nextSeed()) >>> 1)
                ;
        }
        return r;
    }

nextSeed()

nextSeed()方法的作用是獲取隨機(jī)種子,代碼很簡單,就是通過UNSAFE類獲取當(dāng)前線程的threadLocalRandomSeed屬性,并且將原來的threadLocalRandomSeed加上GAMMA設(shè)置成新的threadLocalRandomSeed。

final long nextSeed() {
        Thread t; long r; // read and update per-thread seed
        UNSAFE.putLong(t = Thread.currentThread(), SEED,
                       r = UNSAFE.getLong(t, SEED) + GAMMA);
        return r;
    }

小結(jié):

ThreadLocalRandom為什么線程安全?是因?yàn)樗鼘㈦S機(jī)種子保存在當(dāng)前Thread對象的threadLocalRandomSeed變量中,這樣每個(gè)線程都有自己的隨機(jī)種子,實(shí)現(xiàn)了線程級(jí)別的隔離,所以ThreadLocalRandom也并不需要像Random通過自旋鎖和cas來保證隨機(jī)種子的線程安全性。在高并發(fā)的場景下,效率也會(huì)相對較高。

注:各位有沒有發(fā)現(xiàn)ThreadLocalRandom保證線程安全的方式和ThreadLocal有點(diǎn)像呢

需要注意的點(diǎn):

1.ThreadLocalRandom是單例的。

2.我們每個(gè)線程在獲取隨機(jī)數(shù)之前都需要調(diào)用一下ThreadLocalRandom.current()來初始化當(dāng)前線程的隨機(jī)種子。

3.理解ThreadLocalRandom需要對UnSafe類有所了解,它是Java提供的一個(gè)可以直接通過內(nèi)存對變量進(jìn)行獲取和修改的一個(gè)工具類。java的CAS也是通過這個(gè)工具類來實(shí)現(xiàn)的。

到此這篇關(guān)于java并發(fā)高的情況下用ThreadLocalRandom來生成隨機(jī)數(shù)的文章就介紹到這了,更多相關(guān)java ThreadLocalRandom生成隨機(jī)數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

陕西省| 资溪县| 安阳市| 万荣县| 镇远县| 绵阳市| 吴忠市| 桓台县| 兰州市| 东乌| 鄂托克旗| 龙南县| 瑞安市| 友谊县| 台东市| 东乌| 长沙县| 遂溪县| 绥芬河市| 莱阳市| 大兴区| 阿勒泰市| 长顺县| 沈阳市| 安宁市| 榆社县| 万山特区| 安福县| 桓仁| 靖安县| 宜州市| 静安区| 新宁县| 汉中市| 义乌市| 卢氏县| 米脂县| 健康| 枞阳县| 宣恩县| 纳雍县|