目录
3.1 Random 类及其局限性
java.util.Random 是使用比较广泛的 随机数生成工具类 , 而且 java.lang.Math 中的随机数生成也使用的是 java.util.Random 的实例。public class RandomTest { public static void main(String[] args) { //(1)创建一个默认种子的随机数生成器 Random random = new Random(); //(2)输出10个在0~5(包含0,不包含5)之间的随机数 for (int i = 0; i < 10; ++i) { System.out.println(random.nextInt(5)); } } }
每个 Random 实例里面都有一个原子性的种子变量用来记录当前的种子值, 当要生成新的随机数时需要根据当前种子计算新的种子并更新回原子变量。在多线程 下使用单个 Random 实例生成随机数时,当多个线程同时计算随机数来计算新的种子 时,多个线程会竞争同一个原子变量的更新操作,由于原子变量的更新是 CAS 操作,同 时只有一个线程会成功,所以会造成大量线程进行自旋重试,这会降低并发性能,所以 ThreadLocalRandom 应运而生。
3.2 ThreadLocalRandom
为了弥补多线程高并发情况下 Random 的缺陷,在 JUC 包下新增了 ThreadLocalRandom类。调用 ThreadLocalRandom.current() 来获取当前线程的随机数生成器。public class RandomTest { public static void main(String[] args) { //(10)获取一个随机数生成器 ThreadLocalRandom random = ThreadLocalRandom.current(); //(11)输出10个在0~5(包含0,不包含5)之间的随机数 for (int i = 0; i < 10; ++i) { System.out.println(random.nextInt(5)); } } }
ThreadLocalRandom 的实现原理:
- 从名字上看它会让我们联想到ThreadLocal :ThreadLocal 通过让每一个线程复制一份变量,使得在每个线程对变 量进行操作时实际是操作自己本地内存里面的副本,从而避免了对共享变量进行同步。
- 如果每个线程都维护一个种子变量,则每个线程生成随机数时都根据自己老的种子计算新的种子,并使用新种子更新老的种子,再根据新种子计算随机数,就不会存在竞争问题了,这会大大提高并发性能。
CHAPTER-THREE OVER.......
PROCESS--->3/11