为何ThreadLocalRandom的部分方法未纳入Random类?求客观技术原因
nextInt(least, bound) and nextLong(n) added to Random in Java 8? 这是个挺值得深究的问题,Java 8确实给java.util.Random新增了不少方法(比如各种生成随机流的方法),但偏偏没把ThreadLocalRandom那两个便捷的范围随机方法搬过来,核心原因主要有这么几个客观技术层面的考量:
历史兼容性的严格约束
Random是JDK早期就存在的核心类,Java团队对它的API变更极其谨慎——任何新增方法都必须确保不会破坏已有代码的兼容性。比如nextLong(n)这个方法签名,如果有开发者之前自定义了Random的子类并实现了同名同参数的方法,JDK新增这个方法就会导致子类的实现被覆盖或者引发冲突。而ThreadLocalRandom是JDK 7才引入的新类,完全没有历史包袱,一开始就能安全地加入这些方法。底层实现逻辑的本质差异
ThreadLocalRandom的nextInt(least, bound)和nextLong(n)是基于线程局部的随机状态实现的,不需要CAS操作来保证线程安全,性能更高效。而Random是靠CAS来维护共享的随机种子,把这两个方法移植到Random的话,内部实现需要适配CAS模型,不仅会增加自旋重试的概率(影响性能),还要重新验证均匀分布的正确性——这个验证过程本身就很复杂,不值得为了两个便捷方法冒风险。API定位的刻意区分
Java团队从设计之初就给Random和ThreadLocalRandom划分了明确的使用场景:Random适合单线程或低并发场景,ThreadLocalRandom专门针对高并发优化。把这两个便捷方法留在ThreadLocalRandom里,可以引导开发者根据场景选择合适的类,避免在高并发场景误用Random导致性能问题。如果把方法加到Random里,可能会让开发者忽略两者的性能差异,做出不合适的选择。已有API的功能覆盖
Java 8给Random新增的流API(比如ints(int origin, int bound))其实已经能实现类似nextInt(least, bound)的功能,虽然写法上不是直接调用单个方法,但通过ints(least, bound).findFirst().getAsInt()就能达到目的。Java团队可能认为这种方式已经覆盖了需求,没必要再单独新增重复的方法,而ThreadLocalRandom的方法是作为新类的便捷补充存在的。
内容的提问来源于stack exchange,提问作者DodgyCodeException

