




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第java并发高的情况下用ThreadLocalRandom来生成随机数目录一:简述二:Random的性能差在哪里三:ThreadLocalRandom的简单使用四:为什么ThreadLocalRandom能在保证线程安全的情况下还能有不错的性能
一:简述
如果我们想要生成一个随机数,通常会使用Random类。但是在并发情况下Random生成随机数的性能并不是很理想,今天给大家介绍一下JUC包中的用于生成随机数的类--ThreadLocalRandom.(本文基于JDK1.8)
二:Random的性能差在哪里
Random随机数生成是和种子seed有关,而为了保证线程安全性,Random通过CAS机制来保证线程安全性。从next()方法中我们可以发现seed是通过自旋锁和CAS来进行修改值的。如果在高并发的场景下,那么可能会导致CAS不断失败,从而导致不断自旋,这样就可能会导致服务器CPU过高。
protectedintnext(intbits){
longoldseed,nextseed;
AtomicLongseed=this.seed;
do{
oldseed=seed.get();
nextseed=(oldseed*multiplier+addend)mask;
}while(!pareAndSet(oldseed,nextseed));
return(int)(nextseed(48-bits));
}
三:ThreadLocalRandom的简单使用
使用的方法很简单,通过ThreadLocalRandom.current()获取到ThreadLocalRandom实例,然后通过nextInt(),nextLong()等方法获取一个随机数。
代码:
@Test
voidtest()throwsInterruptedException{
newThread(()-{
ThreadLocalRandomrandom=ThreadLocalRandom.current();
System.out.println(random.nextInt(100));
}).start();
newThread(()-{
ThreadLocalRandomrandom=ThreadLocalRandom.current();
System.out.println(random.nextInt(100));
}).start();
Thread.sleep(100);
}
运行结果:
四:为什么ThreadLocalRandom能在保证线程安全的情况下还能有不错的性能
我们可以看一下ThreadLocalRandom的代码实现。
首先我们很容易看出这是一个饿汉式的单例
/**Constructorusedonlyforstaticsingleton*/
privateThreadLocalRandom(){
initialized=true;//falseduringsuper()call
/**ThecommonThreadLocalRandom*/
staticfinalThreadLocalRandominstance=newThreadLocalRandom();
我们可以看到PROBE成员变量代表的是Thread类的threadLocalRandomProbe属性的内存偏移量,SEED成员变量代表的是Thread类的threadLocalRandomSeed属性的内存偏移量,SECONDARY成员变量代表的是Thread类的threadLocalRandomSecondarySeed属性的内存偏移量。
//Unsafemechanics
privatestaticfinalsun.misc.UnsafeUNSAFE;
privatestaticfinallongSEED;
privatestaticfinallongPROBE;
privatestaticfinallongSECONDARY;
static{
try{
UNSAFE=sun.misc.Unsafe.getUnsafe();
Classtk=Thread.class;
SEED=UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE=UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY=UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
}catch(Exceptione){
thrownewError(e);
}
可以看到Thread类中确实有这三个属性
Thread类:
@sun.misc.Contended("tlr")
//当前Thread的随机种子默认值是0
longthreadLocalRandomSeed;
/**Probehashvalue;nonzeroifthreadLocalRandomSeedinitialized*/
@sun.misc.Contended("tlr")
//用来标志当前Thread的threadLocalRandomSeed是否进行了初始化0代表没有,非0代表已经初始化默认值是0
intthreadLocalRandomProbe;
/**SecondaryseedisolatedfrompublicThreadLocalRandomsequence*/
@sun.misc.Contended("tlr")
//当前Thread的二级随机种子默认值是0
intthreadLocalRandomSecondarySeed;
接下来我们看ThreadLocalRandom.current()方法。
ThreadLocalRandom.current()
ThreadLocalRandom.current()的作用主要是初始化随机种子,并且返回ThreadLocalRandom的实例。
首先通过UNSAFE类获取当前线程的Thread对象的threadLocalRandomProbe属性,看随机种子是否已经初始化。没有初始化,那么调用localInit()方法进行初始化
publicstaticThreadLocalRandomcurrent(){
//获取当前线程的
if(UNSAFE.getInt(Thread.currentThread(),PROBE)==0)
localInit();
returninstance;
}
localInit()
localInit()方法的作用就是初始化随机种子,可以看到代码很简单,就是通过UNSAFE类对当前Thread的threadLocalRandomProbe属性和threadLocalRandomSeed属性进行一个赋值。
staticfinalvoidlocalInit(){
intp=probeGenerator.addAndGet(PROBE_INCREMENT);
intprobe=(p==0)1:p;//skip0
longseed=mix64(seeder.getAndAdd(SEEDER_INCREMENT));
Threadt=Thread.currentThread();
UNSAFE.putLong(t,SEED,seed);
UNSAFE.putInt(t,PROBE,probe);
}
接下来以nextInt()方法为例,看ThreadLocalRandom是如何生成到随机数的。我们可以看出随机数正是通过nextSeed()方法获取到随机种子,然后通过随机种子而生成。所以重点看nextSeed()方法是如何获取到随机种子的。
publicintnextInt(intbound){
if(bound=0)
thrownewIllegalArgumentException(BadBound);
intr=mix32(nextSeed());
intm=bound-1;
if((boundm)==0)//poweroftwo
r=m;
else{//rejectover-representedcandidates
for(intu=r
u+m-(r=u%bound)
u=mix32(nextSeed())1)
returnr;
}
nextSeed()
nextSeed()方法的作用是获取随机种子,代码很简单,就是通过UNSAFE类获取当前线程的threadLocalRandomSeed属性,并且将原来的threadLocalRandomSeed加上GAMMA设置成新的threadLocalRandomSeed。
finallongnextSeed(){
Threadt;longr;//readandupdateper-threadseed
UNSAFE.putLong(t=Thread.currentThread(),SEED,
r=UNSAFE.getLong(t,SEED)+GAMMA);
returnr;
}
小结:
ThreadLocalRandom为什么线程安全?是因为它将随机种子保存在当前Thread对象的threadLocalRandomSeed变量中,这样每个线程都有自己的随机种子,实现了线程级别的隔离,所以ThreadLocalRandom也并不需要像Random通过自旋锁和cas来保证随机种子的线程安全性。在高并发的场景下,效率也会相对较高。
注:各位有没有发现ThreadL
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年精神综合试题及答案
- 家用美容仪器用户手册法规规定考核试卷
- 多式联运与危险货物运输协调考核试卷
- 骨骼健康产品功效成分的提取与纯化技术考核试卷
- 异地招待管理办法
- 专科中医护理试题及答案
- 2024年西藏安多县急诊医学(副高)考试题含答案
- 护士轮转管理办法
- 2024年四川省营山县普通外科学(副高)考试题含答案
- 招标管理办法定标
- 锅炉检修质量培训课件
- ERP系统操作图文介绍流程
- GB/T 12771-2019流体输送用不锈钢焊接钢管
- 低压电工培训教案课件
- 2023年北京信息职业技术学院辅导员招聘考试笔试题库及答案解析
- GB35114-2017公共安全视频监控联网信息安全技术要求
- 水稻的一生课件
- 响应性评审表
- 留守儿童之家各类工作制度
- FIDIC银皮书(中英文对照)
- 暂时进出口协议范本样本
评论
0/150
提交评论