笔者最近在练习Mysql语句优化,奈何年少不懂,找不到百万级别的测试数据,只好用java随机生成数据凑合用一下,因此写下此篇博客,经测试生成500万条数据后台用了9秒,彻底能够接受java
random伪随机数类在 java.util 包下,是最经常使用的随机数生成器,其使用线性同余公式来生成随机数,因此才说是伪随机。该类的实例是线程安全的,多线程并发使用可能会遇到争用问题,这时可用 ThreadLocalRandom 来解决这个问题,此外还有 SecureRandom 、SplittableRandom 随机生成器,这里就不扩展说明了sql
类型 | 名字 | 解释 |
---|---|---|
Random() | 默认构造函数 | |
Random(long seed) | 有参构造,用种子建立伪随机生成器 | |
int | nextInt | 返回生成器中生成表序列中的下一个伪随机数 |
int | nextInt(int n) | 返回均匀分布于区间 [0,n)的伪随机数 |
double | nextDouble | 返回下一个伪随机数 [0.0,1.0) |
先看无参构造,直接上源码安全
// 无参构造也是调用有参构造的,那么放出有参构造,再看里面具体内容 public Random() { this(seedUniquifier() ^ System.nanoTime()); } // 有参构造接收长整型种子参数 public Random(long seed) { // 判断是否本类 if (getClass() == Random.class) // 能够看出长整型种子是Atomic原子型的,即线程安全 // initialScramble() 是seed与两个具体数值运算,这里不给出了 this.seed = new AtomicLong(initialScramble(seed)); else { // subclass might have overriden setSeed // 翻译:子类可能重写setSeed方法 this.seed = new AtomicLong(); setSeed(seed); } } // 再回无参构造内部 // 其中 ^ System.nanoTime() 表示与系统纳秒异或运算,也就是说随机数依赖于时间 this(seedUniquifier() ^ System.nanoTime()); private static final AtomicLong seedUniquifier = new AtomicLong(8682522807148012L); private static long seedUniquifier() { // L'Ecuyer, "Tables of Linear Congruential Generators of // Different Sizes and Good Lattice Structure", 1999 // 翻译:不一样大小结构良好的线性同余生成元表, for (;;) { long current = seedUniquifier.get(); long next = current * 181783497276652981L; // 用到了CAS轻量锁 if (seedUniquifier.compareAndSet(current, next)) return next; } }
再看nextInt方法,有参的方法用逻辑运算把范围指定,这里就不介绍了多线程
public int nextInt() { return next(32); } 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)); // 可能这些位运算就是线性同余把 }
简单使用并发
Random r1 = new Random(); Random r2 = new Random(); Random r3 = new Random(); Random r4 = new Random(1000); Random r5 = new Random(1000); System.out.println(r1.nextInt()); System.out.println(r2.nextInt()); System.out.println(r3.nextInt(100)); System.out.println(r4.nextInt()); System.out.println(r5.nextInt());
491030142 2021835847 49 -1244746321 -1244746321
从结果和源码能够看出:app
new Random.nextInt(int n)
来生成伪随机数
咱们最经常使用仍是这个函数,静态调用方便简单dom
// 底层仍是用了Random类 public static double random() { return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); } // 新建一个依赖时间的随机数生成器 private static final class RandomNumberGeneratorHolder { static final Random randomNumberGenerator = new Random(); } // 位运算增强随机 public double nextDouble() { return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT; }
从源码能够看出:ide
生成给定范围的伪随机数函数
// 给定范围 int min = 10; int max = 15; // 生成伪随机小数 double num = Math.random(); // 范围逻辑运算,想一下很简单的 int rs = (int)(num * (max - min + 1) + min); System.out.println(rs); // 须要整数的位数
// 密码字符范围 String range = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+[];',.<>?:{}|"; // 生成100个伪随机密码 for(int i = 0; i < 100; i++){ // 字符串 StringBuffer bf = new StringBuffer(); // 密码长度8~20 int len = (int)(Math.random() * (20 - 8 + 1) + 8); for(int j = 0; j < len; j++){ int index = new Random().nextInt(range.length()); bf.append(range.charAt(index)); } System.out.println(bf.toString()); }
_ho1O@<s |4z$1sDIDRt_o{PR H_}z;A9;K74amjb2r O;*89#b!|4w|;z?~ s+EmeTCdpJ9?W8,lNNl| o2#P9R@,hFT {+})BECM.Jf|& // 彻底看不懂,还能够加上MD5加密