Java 17 更新(3):随机数生成器来了一波稳稳的增强
JDK 当中的随机数生成器其实对于普通开发者来讲基本够用,不过对于一些比较复杂的场景来讲,原有的类结构对扩展并不是很友好。
- Java 17 更新(0):前言
- Java 17 更新(1):更快的 LTS 节奏
- Java 17 更新(2):没什么存在感的 strictfp 这回算是回光返照了
- Java 17 更新(3):随机数生成器来了一波稳稳的增强
- Java 17 更新(4):这波更新,居然利好 mac 用户
- Java 17 更新(5):历史包袱有点儿大,JDK 也在删代码啦
- Java 17 更新(6):制裁!我自己私有的 API 你们怎么随便一个人都想用?
- Java 17 更新(7):模式匹配要支持 switch 啦
- Java 17 更新(8):密封类终于转正
- Java 17 更新(9):Unsafe 不 safe,我们来一套 safe 的 API 访问堆外内存
- Java 17 更新(10):访问外部函数的新 API,JNI 要凉了?
- Java 17 更新(11):支持矢量运算,利好科学计算?
- Java 17 更新(12):支持上下文的序列化过滤器,又一次给序列化打补丁
这一条更新来自:JEP 356: Enhanced Pseudo-Random Number Generators,相比之下,这一条实用多了。
我们都用过随机数,不过一般情况下我们很少去认真的对待随机数的具体结果,就好像它是真的随机一样。
1 | var random = new Random(System.currentTimeMillis()); |
除了 Random 类,JDK 当中还提供了另外几个随机数的成员:
- ThreadLocalRandom:顾名思义,提供线程间独立的随机序列。它只有一个实例,多个线程用到这个实例,也会在线程内部各自更新状态。它同时也是 Random 的子类,不过它几乎把所有 Random 的方法又实现了一遍。
- SplittableRandom:非线程安全,但可以 fork 的随机序列实现,适用于拆分子任务的场景。
ThreadLocalRandom 继承自 Random,而 SplittableRandom 与它俩则没什么实际的关系,因此如果我们在代码当中想要动态切换 Random 和 SplittableRandom 就只能定义两个成员,并且在用到的地方做判断:
Java 16
1 | SplittableRandom splittableRandom = ...; |
而且如果想要自己扩展随机数的算法,也只能自己去实现,原有的定义方式缺乏一个统一的接口。
Java 17 为了解决这个问题,定义了几个接口:
这样我们就可以面向接口编程啦~
另外,尽管各个实现的细节不太一样,但思路基本上一致,因此老版本当中的几个随机数的类当中存在大量重复或者相似的代码。连 JDK 都存在 CV 代码的情况,那我们为了快速实现需求 CV 代码也不丢人,对不。
Java 17 把这些高度相似的逻辑抽了出来,搞了一个新的类:RandomSupport,又一个 3000 行的 Java 文件。
所以以前:
**Java 16 **
1 | // Random.java |
有相似的地方吧。我们再来看看 Java 17 的实现:
Java 17
1 | // Random.java |
而这个 AbstractSplittableGenerator 就定义在 RandomSupport.java 当中,是 RandomSupport 一个内部类。
你以为这就没了?不是的。提案的说明当中提到,提案的目标不是实现很多的随机数产生算法,不过这次还是添加了一些常见的实现,所以你会在 JDK 17 当中看到多了一个模块:
这些实现都有自己的名字,用注解标注出来,例如:
1 |
|
我们可以通过名字来获取它们的实例:
1 | var random = RandomGenerator.of("L32X64MixRandom"); |
好啦,关于随机数的更新又讲完啦。你不会又觉得这玩意没啥用吧。
关于作者
霍丙乾 bennyhuo,Google 开发者专家(Kotlin 方向);《深入理解 Kotlin 协程》 作者(机械工业出版社,2020.6);《深入实践 Kotlin 元编程》 作者(机械工业出版社,2023.8);移动客户端工程师,先后就职于腾讯地图、猿辅导、腾讯视频。
- GitHub:https://github.com/bennyhuo
- 博客:https://www.bennyhuo.com
- bilibili:霍丙乾 bennyhuo
- 微信公众号:霍丙乾 bennyhuo