代码评审——随机数Random问题

问题描述:

为了获取唯一值,经常会依赖产生随机数来保证唯一性。在获取随机数时,如果使用错误的方法,会比较低效。

可以参考以下代码:

public static String geneRundomNo(){Random r=new Random();int num=r.nextInt(100000);return "" + num;
}

此时,使用静态代码扫描工具,会出现以下提示:
Save and re-use this “Random”.
在这里插入图片描述


原因分析:

可以看下来自静态代码扫描工具的说明:

Creating a new Random object each time a random value is needed is inefficient and may produce numbers which are not random depending on the JDK. For better efficiency and randomness, create a single Random, then store, and reuse it.
The Random() constructor tries to set the seed with a distinct value every time. However there is no guarantee that the seed will be random or even uniformly distributed. Some JDK will use the current time as seed, which makes the generated numbers not random at all.
This rule finds cases where a new Random is created each time a method is invoked and assigned to a local random variable.

简单的说就是每次需要一个随机值时创建一个新的Random对象是低效的,并且可能会根据JDK的版本不同产生非随机的数字。


解决方案:

首先看下静态代码扫描工具给出的建议。

private Random rand = SecureRandom.getInstanceStrong();  // SecureRandom is preferred to Randompublic void doSomethingCommon() {int rValue = this.rand.nextInt();//...

如果按照这个建议执行,那么会产生2个问题

1、按照上述方式引入,还需要解决构建函数的问题。

当引入java.security.SecureRandom后,需要解决构造函数问题。
可以通过以下方式解决:

private static Random rand;
static {try {rand = SecureRandom.getInstanceStrong();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}
}

2、使用SecureRandom.getInstanceStrong()会导致线程阻塞问题,这个问题也是最严重的。

原因:不同的系统环境执行的底层代码不相同,在linux系统中是通过底层NativePRNG方法,通过/dev/random方式读取随机数,/dev/random方式受系统环境的影响容易造成线程阻塞,在windows系统中通过generateSeed的native方法读取,不会阻塞线程。具体的分析过程可以参考《SecureRandom.getInstanceStrong()引发的线程阻塞问题分析》。这篇文章写的非常详细了。

解决方案:使用new SecureRandom()替换SecureRandom.getInstanceStrong()。
请注意:这种解决方案是伪随机。

其他相关知识点:

以下内容摘自文章《SecureRandom 引发的线程阻塞》

  1. SecureRandom本身并不是伪随机算法的实现,而是使用了其他类提供的算法来获取伪随机数。

  2. 如果简单的new一个SecureRandom对象的话,在不同的操作平台会获取到不同的算法,windows默认是SHA1PRNG,Linux的话是NativePRNG。

  3. Linux下的NativePRNG,如果调用generateSeed()方法,这个方法会读取Linux系统的/dev/random文件,这个文件在JAVA_HOME/jre/lib/securiy/java.security里面有默认定义。而/dev/random文件是动态生成的,如果没有数据,就会阻塞。也就造成了第一个现象。

  4. 可以使用-Djava.security.egd=file:/dev/./urandom (这个文件名多个u)强制使用/dev/urandom这个文件,避免阻塞现象。中间加个点的解释是因为某个JDK BUG,SO那个帖子有链接。

  5. 如果使用SecureRandom.getInstanceStrong()这种方法初始化SecureRandom对象的话,会使用NativePRNGBlocking这个算法,而NativePRNGBlocking算法的特性如下:
    NativePRNGBlocking uses /dev/random for all of the following operations:
    Initial seeding: This initializes an internal SHA1PRNG instance using 20 bytes from /dev/random
    Calls to nextBytes(), nextInt(), etc.: This provides the XOR of the output from the internal SHA1PRNG instance (see above) and data read from /dev/random
    Calls to getSeed(): This provides data read from /dev/random
    可见这个算法完全依赖/dev/random,所以当这个文件随机数不够的时候,自然会导致卡顿了。

  6. 如果使用NativePRNGBlocking算法的话,4中的系统参数失效!!!

  7. 一般使用SecureRandom不需要设置Seed,不需要设置算法,使用默认的,甚至一个静态的即可,如果有需求的话可以在运行一段时间后setSeed一下

参考文章:《一文详解安全随机数》这篇文章详细介绍了如何使用安全随机数。

如果这篇博客对大家有所帮助,我希望能得到各位的免费点赞收藏,作为对我的鼓励和支持。
同时,也请大家在评论区留下您宝贵的意见和建议,我将非常欢迎。
感谢大家的支持评论收藏!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/427767.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式】适配器模式怎么理解?

什么是转换器模式? 转换器模式是一种结构型设计模式,主要用于在两种不同类型的对象之间进行转换,而不需要改变原型的实际逻辑。这是一种在软件设计中经常使用的模式,它有助于保持代码的整洁和组织。在软件开发中,我们…

中国劳动统计年鉴,涵盖2011-2021年,多项劳动指标可看

基本信息. 数据名称: 中国劳动统计年鉴 数据格式: 其他 数据时间: 2011-2021年 数据几何类型: 无 数据坐标系: WGS84 数据来源:网络公开数据 示例数据: 一、综合1-1全国劳动统计主要指标1-2人口数及构成(年末数)1-3国内生产总值及构成1-3续表…

【刷题】 leetcode 面试题 01.06 字符串压缩

字符串压缩 字符串压缩思路一(双指针顺畅版)思路二(sprintf函数巧解版) Thanks♪(・ω・)ノ谢谢阅读下一篇文章见!!! 字符串压缩 来看题目: 根据题目…

vue实现搜索文字高亮

在日常项目中我们往往会有搜索高亮的需求&#xff0c;下面方法可帮助我们实现&#xff0c;可能不是最优但是可以解决 代码实现 <template><div><el-input v-model"searchText" placeholder"Type a word to highlight" input"changei…

C++补充篇- C++11 及其它特性

目录 explicit 关键字 左值和右值的概念 函数返回值当引用 C11 新增容器 - array C的类型转换 static_cast reinterpret_cast dynamic_cast const_cast C智能指针 auto_ptr 使用详解 (C98) unique_ptr 使用详解 (C11) auto_ptr的弊端 unique_ptr严谨auto_ptr的弊端 unique_…

CSS 楼梯弹弹球

<template><view class="loader"></view> </template><script></script><style>body {background-color: #212121;/* 设置背景颜色为 #212121 */}.loader {position: relative;/* 设置定位为相对定位 */width: 120px;/* 设…

面试题-【消息队列】

消息队列 问题1 如何进行消息队列的技术选型优点解耦 &#xff08;pub/sub模型&#xff09;异步&#xff08;异步接口性能优化&#xff09;削峰 使用消息队列的缺点几种消息队列的特性 问题2 引入消息队列之后该如何保证其高可用性RabbitMQ的高可用kafka高可用 问题3 在消息队列…

mysql 基础(三)

一、多表设计 数据库设计范式 第一范式(确保每列保持原子性) 第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值&#xff0c;就说明该数据库表满足了第一范式。第二范式就是要有主键&#xff0c;要求其他字段都依赖于主键。 没有主键就没有唯一性&…

硬件基础:组合逻辑电路

什么是组合逻辑电路 组合逻辑电路是由一些基本的逻辑门电路组成的&#xff0c;没有反馈&#xff0c;输出仅取决于输入。 组合逻辑电路是数字逻辑电路中一种重要的电路类型&#xff0c;它是由多个逻辑门&#xff08;例如与门、或门、非门等&#xff09;组成的电路。组合逻辑电路…

保姆级教程: GPTs接入广告到提现成功全过程真实记录

因为相信&#xff0c;所以看见 &#x1f31f; 1月19日&#xff0c;在AI社群首次了解到GPTs能通过接入广告获得收益。虽然对收益的多少和提现的可行性有所疑问&#xff0c;但我还是立刻在我的GPTs上尝试了这一功能。这一探索的旅程&#xff0c;如同跨入了一个未知的新世界。我的…

live555在拉流时应对多路码流传输带宽问题的几种处理思路

处理带宽管理和调整的机制 Live555库本身并没有直接处理带宽管理和调整的机制&#xff0c;因为它主要是一个用于实现RTSP流媒体服务器和客户端的库&#xff0c;而带宽管理通常是在应用层进行处理的。但Live555支持一些基础协议&#xff0c;这些协议可以在应对带宽问题时进行使用…

[pytorch入门] 6. 神经网络

基本介绍 torch.nn&#xff1a; Containers&#xff1a;基本骨架Convolution Layers&#xff1a; 卷积层Pooling layers&#xff1a;池化层Non-linear Activations (weighted sum, nonlinearity)&#xff1a;非线性激活Normalization Layers&#xff1a;正则化层 Container…