java中ThreadLocalRandom的使用

在java中我们通常会需要使用到java.util.Random来便利的生产随机数。但是Random是线程安全的,如果要在线程环境中的话就有可能产生性能瓶颈。

我们以Random中常用的nextInt方法为例来具体看一下:

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

nextInt方法实际上调用了下面的方法:

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

从代码中我们可以看到,方法内部使用了AtomicLong,并调用了它的compareAndSet方法来保证线程安全性。所以这个是一个线程安全的方法。

其实在多个线程环境中,Random根本就需要共享实例,那么该怎么处理呢?

在JDK 7 中引入了一个ThreadLocalRandom的类。ThreadLocal大家都知道就是线程的本地变量,而ThreadLocalRandom就是线程本地的Random。

我们看下怎么调用:

ThreadLocalRandom.current().nextInt();

我们来为这两个类分别写一个benchMark测试:

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

分析运行结果,我们可以看出ThreadLocalRandom在多线程环境中会比Random要快。

本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/ThreadLocalRandom

更新文章请参考flydean的博客

java中ThreadLocalRandom的使用的更多相关文章

  1. java中ThreadLocalRandom类和Random类的使用

    package frank; import java.lang.*; import java.util.*;//工具类一般都在util里面 import java.util.concurrent.Th ...

  2. Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom

    Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom 文中的 Random即:java.util.Random,ThreadLocalRandom 即: ...

  3. java中多线程中Runnable接口和Thread类介绍

    java中的线程时通过调用操作系统底层的线程来实现线程的功能的. 先看如下代码,并写出输出结果. // 请问输出结果是什么? public static void main(String[] args ...

  4. Java中基础类库使用

    Java中基础类库: 在这里我仅仅介绍几种我个人觉得会常常使用的 1:Object类中的Clone机制仅仅是对对象进行浅层次的克隆,假设须要进行深层次的克隆的话那么就要自己写(详细Clone方法请參考 ...

  5. 沉淀再出发:java中的HashMap、ConcurrentHashMap和Hashtable的认识

    沉淀再出发:java中的HashMap.ConcurrentHashMap和Hashtable的认识 一.前言 很多知识在学习或者使用了之后总是会忘记的,但是如果把这些只是背后的原理理解了,并且记忆下 ...

  6. java中的锁

    java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够.于是再次翻看了一下书里的内容,突然有点打开脑门的感觉.看来确实是要学习的最好方式 ...

  7. java中的字符串相关知识整理

    字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...

  8. Java中的Socket的用法

                                   Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...

  9. java中Action层、Service层和Dao层的功能区分

    Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...

随机推荐

  1. memcached-tool 工具

    perl memcached-tool server_ip:port stats 输出说明: pid memcache服务器的进程ID uptime 服务器已经运行的秒数 time 服务器当前的uni ...

  2. 《Three.js 入门指南》3.1.2 - 一份整齐的代码结构以及使用ORBIT CONTROLS插件(轨道控制)实现模型控制

    3.1.2 正式代码结构 & ORBIT CONTROLS插件(轨道控制) 说明 本节内容属于插入节,<Three.js入门指南>这本书中,只是简单的介绍了一些概念,是一本基础的入 ...

  3. CAS单点登录系列之极速入门于实战教程(4.2.7)

    @ 目录 一. SSO简介 1.1 单点登录定义 1.2 单点登录角色 1.3 单点登录分类 二. CAS简介 2.1 CAS简单定义 2.2 CAS体系结构 2.3 CAS原理 三.CAS服务端搭建 ...

  4. pm2 开机启动egg项目

    1.在服务器上安装PM2 npm install pm2 -g 2.对PM2进行更新 pm2 update 3.进入服务器中egg项目更目录,并新建server.js文件,并在其中写入以下代码 con ...

  5. Hadoop(十一):组合任务概述和格式

    组合任务概述 一些复杂的任务很难由一个MR处理完成,所以一般需要将其拆分成为多个简单的MR子任务来执行. MapReduce框架中对于这类的问题提供了几种方式进行任务执行流程的控制,主要包括以下几种方 ...

  6. sqlchemy的外键及其约束条件

    外键创建 使用sqlalchemy创建外键非常简单.在表中增加一个字段,制定这个字段外键的是哪个表的哪个字段就可以了. 从表中外键定义的字段必须和主键字段类型保持一致. 实例代码: import mo ...

  7. Adb adb push (remote write failed: No space left on device)

    修改完成程序后, mm 后, 准备要push 进到公司测试手机里面的.之前还真的没有遇到过这个问题,查了一下, 应该是手机没空间了的 sudo adb root sudo adb remount su ...

  8. 【第一章】黎姿的python学习笔记

  9. xftp连接centos7

    1.下载xftp文件,并正常进行安装 2.安装好之后运行,并新建会话,此时可见如下界面: 注意: 名称,可随便输入,自己能看懂是什么就行      主机,输入当前Linux服务器的ip(如何获取服务器 ...

  10. 查看jdk 线程 日志

    命令:jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令 这些命令 必须 在 linux jdk bin 路径 下执行 eq: ./jstack 10303 即可  如果想把 ...