java中ThreadLocalRandom的使用詳解
在java中我們通常會(huì)需要使用到j(luò)ava.util.Random來(lái)便利的生產(chǎn)隨機(jī)數(shù)。但是Random是線程安全的,如果要在線程環(huán)境中的話就有可能產(chǎn)生性能瓶頸。
我們以Random中常用的nextInt方法為例來(lái)具體看一下:
public int nextInt() {
return next(32);
}
nextInt方法實(shí)際上調(diào)用了下面的方法:
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));
}
從代碼中我們可以看到,方法內(nèi)部使用了AtomicLong,并調(diào)用了它的compareAndSet方法來(lái)保證線程安全性。所以這個(gè)是一個(gè)線程安全的方法。
其實(shí)在多個(gè)線程環(huán)境中,Random根本就需要共享實(shí)例,那么該怎么處理呢?
在JDK 7 中引入了一個(gè)ThreadLocalRandom的類。ThreadLocal大家都知道就是線程的本地變量,而ThreadLocalRandom就是線程本地的Random。
我們看下怎么調(diào)用:
ThreadLocalRandom.current().nextInt();
我們來(lái)為這兩個(gè)類分別寫一個(gè)benchMark測(cè)試:
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())
// 預(yù)熱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())
// 預(yù)熱5輪
.warmupIterations(5)
// 度量10輪
.measurementIterations(10)
.forks(1)
.build();
new Runner(opt).run();
}
}
分析運(yùn)行結(jié)果,我們可以看出ThreadLocalRandom在多線程環(huán)境中會(huì)比Random要快。
本文的例子可以參考https://github.com/ddean2009/learn-java-concurrency/tree/master/ThreadLocalRandom
到此這篇關(guān)于java中ThreadLocalRandom的使用詳解的文章就介紹到這了,更多相關(guān)java ThreadLocalRandom內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring MVC Mybatis多數(shù)據(jù)源的使用實(shí)例解析
項(xiàng)目需要從其他網(wǎng)站獲取數(shù)據(jù),因?yàn)槭桥R時(shí)加的需求,這篇文章主要介紹了Spring MVC Mybatis多數(shù)據(jù)源的使用實(shí)例解析,需要的朋友可以參考下2016-12-12
springAOP完整實(shí)現(xiàn)過(guò)程
當(dāng)你調(diào)用SimpleService類的doSomething方法時(shí),上述的PerformanceAspect會(huì)自動(dòng)攔截此調(diào)用,并且記錄該方法的執(zhí)行時(shí)間,這樣你就完成了一個(gè)針對(duì)Spring的AOP入門級(jí)案例,感興趣的朋友一起看看吧2024-02-02
Android開(kāi)發(fā)Kotlin實(shí)現(xiàn)圓弧計(jì)步器示例詳解
這篇文章主要為大家介紹了Android開(kāi)發(fā)Kotlin繪制圓弧計(jì)步器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
java組件smartupload實(shí)現(xiàn)上傳文件功能
這篇文章主要為大家詳細(xì)介紹了java組件smartupload實(shí)現(xiàn)上傳文件功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
SpringBoot中登錄驗(yàn)證碼的4種實(shí)現(xiàn)方案
這篇文章主要介紹了在SpringBoot應(yīng)用中實(shí)現(xiàn)四種登錄驗(yàn)證碼的技術(shù)方案,包括圖形驗(yàn)證碼、短信驗(yàn)證碼、郵箱驗(yàn)證碼和滑動(dòng)拼圖驗(yàn)證碼,需要的可以參考下2025-04-04
java?mybatis如何操作postgresql?array數(shù)組類型
這篇文章主要介紹了java?mybatis如何操作postgresql?array數(shù)組類型,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01

