Random类及其局限性
每个Random实例里都有一个原子性的种子变量用来记录当前种子值,当要生成新随机数时根据当前种子计算新种子并更新回原子变量。多线程下使用单个Random实例生成随机数时,多个线程同时计算随机数来计算新种子时,多个线程会竞争同一原子变量,由于原子变量更新是CAS操作,所以只有一个线程成功,其他线程自旋重试,降低并发性能。
ThreadLocalRandom
继承了Random类并重写了nextInt方法。ThreadLocalRandom并没有存放具体种子,而是存放在调用线程的threadLocalRandomSeed变量。当调用ThreadLocalRandom的current()方法时,ThreadLocalRandom初始化threadLocalRandomSeed变量。
当调用ThreadLocalRandom的nextInt()方法时,实际是获取threadLocalRandomSeed变量作为种子计算新种子并更新到threadLocalRandomSeed变量,再去计算随机数。
注意:threadLocalRandomSeed变量就是Thread类里的普通long变量,并非原子性变量(变量是线程级别的,无需原子性)