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

java.util.Random和concurrent.ThreadLocalRandom使用對比

 更新時(shí)間:2024年07月04日 10:33:14   作者:xindoo  
這篇文章主要介紹了java.util.Random和concurrent.ThreadLocalRandom使用對比,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

java.util.Random和concurrent.ThreadLocalRandom對比

最近工作中遇到了一個(gè)需求

需要以一定的概率過濾掉一部分的流量,想想只能用Random了,因?yàn)槭窃诙嗑€程環(huán)境下,我還特意確認(rèn)了下Random在多線程是否能正常運(yùn)行,Random的實(shí)現(xiàn)也比較簡單,初始化的時(shí)候用當(dāng)前的事件來初始化一個(gè)隨機(jī)數(shù)種子,然后每次取值的時(shí)候用這個(gè)種子與有些MagicNumber運(yùn)算,并更新種子。

最核心的就是這個(gè)next的函數(shù),不管你是調(diào)用了nextDouble還是nextInt還是nextBoolean,Random底層都是調(diào)這個(gè)next(int bits)。

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

為了保證多線程下每次生成隨機(jī)數(shù)都是用的不同

next()得保證seed的更新是原子操作,所以用了AtomicLong的compareAndSet(),該方法底層調(diào)用了sum.misc.Unsafe的compareAndSwapLong(),也就是大家常聽到的CAS, 這是一個(gè)native方法,它能保證原子更新一個(gè)數(shù)?! ?/p>

既然Random滿足我的需求,又能在多線程下正常運(yùn)行,所以我直接用了random,后來在codeReview中,同事提出用concurrent.ThreadLocalRandom來替代Random。

我腦子里立馬冒出一個(gè)問題,既然random是線程安全的,為什么concurrent包里還要實(shí)現(xiàn)一個(gè)random。

在oracle的jdk文檔里發(fā)現(xiàn)這樣一句話:

use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention. Use of ThreadLocalRandom is particularly appropriate when multiple tasks (for example, each a ForkJoinTask) use random numbers in parallel in thread pools.

大意就是用ThreadLocalRandom更適合用在多線程下,能大幅減少多線程并行下的性能開銷和資源爭搶?! ?/p>

既然文檔里說的牛,到底能有多少的性能提升?

我做了一個(gè)簡單的測試。

測試環(huán)境:

24核 CPU, jdk8,每個(gè)隨機(jī)生成100000個(gè)double數(shù),分別測試不同線程數(shù)下rando和ThreadLocalRandom的運(yùn)行時(shí)間,數(shù)據(jù)如下:

這里寫圖片描述

ThreadNum,Random,ThreadLocalRandom 
50,1192,575
100,4031,162
150,6068,223
200,8093,287
250,10049,248
300,12346,200
350,14429,212
400,16491,62
450,18475,96
500,11311,97
550,12421,90
600,13577,102
650,14718,111
700,15896,127
750,17101,129
800,17907,203
850,19261,226
900,21576,151
950,22206,147
1000,23418,174

ThreadLocalRandom雖然也有波動,但基本上是平的,而random隨著線程數(shù)的增加一直在增加,在1000個(gè)線程時(shí)兩者居然有百倍的性能差距。

不過這里有個(gè)讓人百思不得其解的現(xiàn)象,為什么random的耗時(shí)在500個(gè)線程的時(shí)候又掉下來,測試多次都是這個(gè)情況,可見并不是偶發(fā)現(xiàn)象。

我也在本人的筆記本上測了下,我筆記本雙核i7,ThreadLocalRandom和Random性能差距最高也有100倍,我發(fā)現(xiàn)我筆記本比公司服務(wù)器跑的快(數(shù)據(jù)如下)。。。。

我也在一臺1核的阿里云ECS上測試了,按道理1核心的技術(shù)上,即便是多線程起始也是串行執(zhí)行的,但ThreadLocalRandom和Random在1000個(gè)線程的情況下也有6倍的性能差距。

  這里寫圖片描述

既然ThreadLocalRandom在多線程下表現(xiàn)這么牛,它究竟是如何做到的?

我們來看下源碼,它的核心代碼是這個(gè):

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

起始ThreadLocalRandom是對每個(gè)線程都設(shè)置了單獨(dú)的隨機(jī)數(shù)種子,這樣就不會發(fā)生多線程同時(shí)更新一個(gè)數(shù)時(shí)產(chǎn)生的資源爭搶了,用空間換時(shí)間?! ?/p>

附上Random和ThreadLocalRandom的性能測試代碼

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

public class RandomTest {
    private static Random random = new Random();

    private static final int N = 100000;
//    Random from java.util.concurrent.
    private static class TLRandom implements Runnable {
        @Override
        public void run() {
            double x = 0;
            for (int i = 0; i < N; i++) {
                x += ThreadLocalRandom.current().nextDouble();
            }
        }
    }

//    Random from java.util
    private static class URandom implements Runnable {
        @Override
        public void run() {
            double x = 0;
            for (int i = 0; i < N; i++) {
                x += random.nextDouble();
            }
        }
    }

    public static void main(String[] args) {
        System.out.println("threadNum,Random,ThreadLocalRandom");
        for (int threadNum = 50; threadNum <= 2000; threadNum += 50) {
            ExecutorService poolR = Executors.newFixedThreadPool(threadNum);
            long RStartTime = System.currentTimeMillis();
            for (int i = 0; i < threadNum; i++) {
                poolR.execute(new URandom());
            }
            try {
                poolR.shutdown();
                poolR.awaitTermination(100, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String str = "" + threadNum +"," + (System.currentTimeMillis() - RStartTime)+",";

            ExecutorService poolTLR = Executors.newFixedThreadPool(threadNum);
            long TLRStartTime = System.currentTimeMillis();
            for (int i = 0; i < threadNum; i++) {
                poolTLR.execute(new TLRandom());
            }
            try {
                poolTLR.shutdown();
                poolTLR.awaitTermination(100, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(str + (System.currentTimeMillis() - TLRStartTime));
        }
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用Springboot+Vue實(shí)現(xiàn)文件上傳和下載功能

    使用Springboot+Vue實(shí)現(xiàn)文件上傳和下載功能

    本文介紹了如何使用Springboot結(jié)合Vue進(jìn)行圖書信息管理系統(tǒng)開發(fā),包括數(shù)據(jù)庫表的創(chuàng)建,實(shí)體類、Dao層、Service層和Controller層的編寫,重點(diǎn)講解了文件上傳和下載功能的實(shí)現(xiàn),感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • C# 中Excel導(dǎo)入時(shí)判斷是否被占用三種方法

    C# 中Excel導(dǎo)入時(shí)判斷是否被占用三種方法

    這篇文章主要介紹了C# 中Excel導(dǎo)入時(shí) 判斷是否被占用三種方法的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 詳解Java的Hibernate框架中的注解與緩存

    詳解Java的Hibernate框架中的注解與緩存

    這篇文章主要介紹了詳解Java的Hibernate框架中的注解與緩存,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • java日期處理工具類

    java日期處理工具類

    這篇文章主要為大家詳細(xì)介紹了java日期處理工具類,其次還介紹了日期處理的基礎(chǔ)知識,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • SpringBoot+MyBatis實(shí)現(xiàn)數(shù)據(jù)庫字段級加密

    SpringBoot+MyBatis實(shí)現(xiàn)數(shù)據(jù)庫字段級加密

    在數(shù)據(jù)安全越來越受重視的今天,如何保護(hù)用戶的敏感信息成為每個(gè)開發(fā)者都要面對的問題,本文將分享一個(gè)基于注解的自動加解密方案,感興趣的小伙伴可以了解下
    2025-11-11
  • Java中的Schema校驗(yàn)技術(shù)與實(shí)踐示例詳解

    Java中的Schema校驗(yàn)技術(shù)與實(shí)踐示例詳解

    本主題詳細(xì)介紹了在Java環(huán)境下進(jìn)行XML Schema和JSON Schema校驗(yàn)的方法,包括使用JAXP、JAXB以及專門的JSON校驗(yàn)庫等技術(shù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-09-09
  • 深入了解Java核心類庫--Arrays類

    深入了解Java核心類庫--Arrays類

    這篇文章主要為大家詳細(xì)介紹了java Arrays類定義與使用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-07-07
  • Java中操作Word修訂功能的示例詳解

    Java中操作Word修訂功能的示例詳解

    Word的修訂功能是一種在文檔中進(jìn)行編輯和審閱的功能,它允許多個(gè)用戶對同一文檔進(jìn)行修改并跟蹤這些修改,以便進(jìn)行審查和接受或拒絕修改,下面我們就來學(xué)習(xí)一下Java中操作Word修訂功能的方法,需要的可以參考下
    2023-12-12
  • Spring Boot 鉤子全集實(shí)戰(zhàn)EnvironmentPostProcessor全解

    Spring Boot 鉤子全集實(shí)戰(zhàn)EnvironmentPostProcessor全解

    文章詳細(xì)介紹了SpringBoot中的EnvironmentPostProcessor擴(kuò)展點(diǎn),該點(diǎn)在配置加載階段提供強(qiáng)大的定制化能力,適用于配置中心化、加密解密、動態(tài)覆蓋和校驗(yàn)等場景,感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • spring-mybatis獲取mapper的四種方式匯總

    spring-mybatis獲取mapper的四種方式匯總

    這篇文章主要介紹了spring-mybatis獲取mapper的四種方式匯總,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論

赫章县| 富平县| 抚远县| 延长县| 浑源县| 佛坪县| 塘沽区| 德格县| 临颍县| 肇东市| 新化县| 乌鲁木齐县| 米易县| 古浪县| 韶关市| 岳普湖县| 梓潼县| 孙吴县| 嘉祥县| 筠连县| 阿荣旗| 玉田县| 颍上县| 潮州市| 宁蒗| 龙江县| 沾化县| 昌乐县| 乐业县| 高密市| 伽师县| 东方市| 阳曲县| 柯坪县| 兴化市| 罗平县| 云安县| 平遥县| 安国市| 广德县| 体育|