当前位置: 首页 > news >正文

手机网站导航特效html网页制作代码大全菜鸟

手机网站导航特效,html网页制作代码大全菜鸟,会计可以做网站么,网站推广营销效果转载自 Java中随机数的原理#xff0c;以及使用时的注意点 1 前言 一提到 Java 中的随机数#xff0c;很多人就会想到 Random#xff0c;当出现生成随机数这样需求时#xff0c;大多数人都会选择使用 Random 来生成随机数。Random 类是线程安全的#xff0c;但其内部使…转载自   Java中随机数的原理以及使用时的注意点 1 前言 一提到 Java 中的随机数很多人就会想到 Random当出现生成随机数这样需求时大多数人都会选择使用 Random 来生成随机数。Random 类是线程安全的但其内部使用 CAS 来保证线程安全性在多线程并发的时候它的表现是存在优化空间的。在 JDK1.7 之后Java 提供了更好的解决方案 ThreadLocalRandom接下来我们一起探讨下这几个随机数生成器的实现到底有何不同。 2 Random Random 这个类是 JDK 提供的用来生成随机数的一个类这个类并不是真正的随机而是伪随机伪随机的意思是生成的随机数其实是有一定规律的而这个规律出现的周期随着伪随机算法的优劣而不同一般来说周期比较长但是可以预测。通过下面的代码我们可以对 Random 进行简单的使用:  public class RandomDemo {public static void main(String[] args) {Random rand  new Random();System.out.println(rand.nextInt());System.out.println(rand.nextInt(10));} }Random原理 Random 中的方法比较多这里就针对比较常见的 nextInt() 和 nextInt(int bound) 方法进行分析前者会计算出 int 范围内的随机数后者如果我们传入 10那么他会返回 [0,10) 之间的 int 类型的随机数左闭右开。我们首先看一下 Random() 的构造方法:  public Random() {// 默认构造方法传入的seed值, // 这个值由种子算法得到的一个唯一值与纳秒值通过位运算得到// 尽可能做到了和另一个构造方法的seed值的不同this(seedUniquifier() ^ System.nanoTime()); }public Random(long seed) {if (getClass()  Random.class)this.seed  new AtomicLong(initialScramble(seed));else {// subclass might have overriden setSeedthis.seed  new AtomicLong();setSeed(seed);} }private static long seedUniquifier() {// LEcuyer, Tables of Linear Congruential Generators of// Different Sizes and Good Lattice Structure, 1999for (;;) {long current  seedUniquifier.get();long next  current * 181783497276652981L;if (seedUniquifier.compareAndSet(current, next))return next;} }private static final AtomicLong seedUniquifier  new AtomicLong(8682522807148012L);可以发现在构造方法当中根据当前时间(纳秒)的种子生成了一个 AtomicLong 类型的 seed这也是我们后续的关键所在。 nextInt() nextInt() 的代码如下所示 public int nextInt() {return next(32); }这个里面直接调用的是 next() 方法传入的 32代指的是 Int 类型的位数。 protected int next(int bits) {long oldseed, nextseed;AtomicLong seed  this.seed;do {oldseed  seed.get();// 根据一定的规则生成nextseednextseed  (oldseed * multiplier  addend)  mask;// 更新oldseed的值通过cas保证线程安全} while (!seed.compareAndSet(oldseed, nextseed));// 返回前还需要位运算return (int)(nextseed  (48 - bits)); }这里会根据 seed 当前的值通过一定的规则((oldseed * multiplier addend) mask; 即伪随机算法)算出下一个 seed然后进行 CAS如果 CAS 失败则继续循环上面的操作。最后根据我们需要的 bit 位数来进行返回。核心便是 CAS 算法。 nextInt(int bound) nextInt(int bound) 的代码如下所示 public int nextInt(int bound) {if (bound  0)throw new IllegalArgumentException(BadBound);int r  next(31);int m  bound - 1;if ((bound  m)  0)  // i.e., bound is a power of 2r  (int)((bound * (long)r)  31);else {for (int u  r;u - (r  u % bound)  m  0;u  next(31));}return r; }这个流程比 nextInt() 多了几步具体步骤如下: 首先获取 31 位的随机数注意这里是 31 位和上面 32 位不同因为在 nextInt() 方法中可以获取到随机数可能是负数而 nextInt(int bound) 规定只能获取到 [0,bound) 之前的随机数也就意味着必须是正数预留一位符号位所以只获取了31位。(不要想着使用取绝对值这样操作会导致性能下降)然后进行取 bound 操作。如果 bound 是2的幂次方可以直接将第一步获取的值乘以 bound 然后右移31位解释一下:如果 bound 是4那么乘以4其实就是左移2位其实就是变成了33位再右移31位的话就又会变成2位最后2位 int 的范围其实就是 [0,4) 了。如果不是 2 的幂通过模运算进行处理。并发瓶颈 一般而言CAS 相比加锁有一定的优势但并不一定意味着高效并发很大的情况下回造成CPU飙高。一个立刻被想到的解决方案是每次使用 Random 时都去 new 一个新的线程私有化的 Random 对象或者使用 ThreadLocal 来维护线程私有化对象但除此之外还存在更高效的方案下面便来介绍本文的主角 ThreadLocalRandom。 3 ThreadLocalRandom 在 JDK1.7 之后提供了新的类 ThreadLocalRandom 用来在并发场景下代替 Random。使用方法比较简单: public class RandomTest {public static void main(String[] args) {System.out.println(ThreadLocalRandom.current().nextInt());System.out.println(ThreadLocalRandom.current().nextInt());System.out.println(ThreadLocalRandom.current().nextInt(10));} }在 current 方法中有: public static ThreadLocalRandom current() {if (UNSAFE.getInt(Thread.currentThread(), PROBE)  0)// 判断当前线程是否初始化, 如果没有则初始化localInit();return instance; }static final void localInit() {int p  probeGenerator.addAndGet(PROBE_INCREMENT);int probe  (p  0) ? 1 : p; // skip 0long seed  mix64(seeder.getAndAdd(SEEDER_INCREMENT));Thread t  Thread.currentThread();UNSAFE.putLong(t, SEED, seed);UNSAFE.putInt(t, PROBE, probe); }可以看见如果没有初始化会对其进行初始化而这里我们的 seed 不再是一个全局变量而是每个线程私有的在我们的Thread中有三个变量:  threadLocalRandomSeedThreadLocalRandom 使用它来控制随机数种子。threadLocalRandomProbeThreadLocalRandom 使用它来控制初始化。threadLocalRandomSecondarySeed二级种子。 可以看见所有的变量都加了 sun.misc.Contended 这个注解用来处理伪共享问题。 在 nextInt() 方法当中代码如下: public int nextInt() {return mix32(nextSeed()); }final long nextSeed() {Thread t; long r; // read and update per-thread seedUNSAFE.putLong(t  Thread.currentThread(), SEED,r  UNSAFE.getLong(t, SEED)  GAMMA);return r; }我们的关键代码如下: UNSAFE.putLong(t Thread.currentThread(), SEED,rUNSAFE.getLong(t, SEED) GAMMA); 可以看见由于我们每个线程各自都维护了种子这个时候并不需要 CAS直接进行 put在这里利用线程之间隔离减少了并发冲突相比较 ThreadLocalRandomThreadLocalRandom 不仅仅减少了对象维护的成本其内部实现也更轻量级。所以 ThreadLocalRandom 性能很高。 4 性能测试 除了文章中详细介绍的 RandomThreadLocalRandom我还将 netty4 实现的 ThreadLocalRandom以及 ThreadLocalRandom 作为参考对象一起参与 JMH 测评。 BenchmarkMode({Mode.AverageTime}) OutputTimeUnit(TimeUnit.NANOSECONDS) Warmup(iterations 3, time 5) Measurement(iterations 3, time 5) Threads(50) Fork(1) State(Scope.Benchmark) public class RandomBenchmark {Random random new Random();ThreadLocalRandom threadLocalRandomHolder ThreadLocal.withInitial(Random::new);Benchmarkpublic int random() {return random.nextInt();}Benchmarkpublic int threadLocalRandom() {return ThreadLocalRandom.current().nextInt();}Benchmarkpublic int threadLocalRandomHolder() {return threadLocalRandomHolder.get().nextInt();}Benchmarkpublic int nettyThreadLocalRandom() {return io.netty.util.internal.ThreadLocalRandom.current().nextInt();}public static void main(String[] args) throws RunnerException {Options opt new OptionsBuilder().include(RandomBenchmark.class.getSimpleName()).build();new Runner(opt).run();}} 测评结果如下 Benchmark                                Mode  Cnt     Score     Error  Units RandomBenchmark.nettyThreadLocalRandom   avgt    3   192.202 ± 295.897  ns/op RandomBenchmark.random                   avgt    3  3197.620 ± 380.981  ns/op RandomBenchmark.threadLocalRandom        avgt    3    90.731 ±  39.098  ns/op RandomBenchmark.threadLocalRandomHolder  avgt    3   229.502 ± 267.144  ns/op 从上图可以发现JDK1.7 的 ThreadLocalRandom 取得了最好的成绩仅仅需要 90 ns 就可以生成一次随机数netty 实现的 ThreadLocalRandom 以及使用 ThreadLocal 维护 Random 的方式差距不是很大位列 2、3 位共享的 Random 变量则效果最差。 可见在并发场景下ThreadLocalRandom 可以明显的提升性能。 5 注意点 注意ThreadLocalRandom 切记不要调用 current 方法之后作为共享变量使用 public class WrongCase {ThreadLocalRandom threadLocalRandom ThreadLocalRandom.current()public int concurrentNextInt(){return threadLocalRandom.nextInt();}} 这是因为 ThreadLocalRandom.current() 会使用初始化它的线程来填充随机种子这会带来导致多个线程使用相同的 seed。 public class BadCase {public static void main(String[] args) {ThreadLocalRandom rand  ThreadLocalRandom.current();for (int i  0; i  10; i) {new Thread(() - {System.out.println(rand.nextInt());}).start();}} }输出相同的随机数 -1667209487 -1667209487 -1667209487 -1667209487 -1667209487 -1667209487 -1667209487 -1667209487 -1667209487 -1667209487 确保不同线程获取不同的 seed最简单的方式便是每次调用都是使用 current() public class GoodCase {public static void main(String[] args) {for (int i  0; i  3; i) {new Thread(() - {System.out.println(ThreadLocalRandom.current().nextInt());System.out.println(ThreadLocalRandom.current().nextInt());System.out.println(ThreadLocalRandom.current().nextInt());}).start();}} }彩蛋1 梁飞博客中一句话常常在我脑海中萦绕魔鬼在细节中。优秀的代码都是一个个小细节堆砌出来今天介绍的 ThreadLocalRandom 也不例外。 在 incubator-dubbo-2.7.0 中随机负载均衡器的一个小改动便是将 Random 替换为了 ThreadLocalRandom用于优化并发性能。 彩蛋2 ThreadLocalRandom 的 nextInt(int bound) 方法中当 bound 不为 2 的幂次方时进入 else 分支使用了一个循环来修改 r 的值我认为这可能不必要你觉得呢 public int nextInt(int bound) {if (bound 0)throw new IllegalArgumentException(BadBound);int r mix32(nextSeed());int m bound - 1;if ((bound m) 0) // power of twor m;else { // reject over-represented candidatesfor (int u r 1;u m - (r u % bound) 0;u mix32(nextSeed()) 1);}return r;}
http://www.zqtcl.cn/news/512831/

相关文章:

  • 苏州做网站的公司排名泉州网络推广专员
  • 无为县做互联网网站备案的时候网站建设方案书要吗
  • 修改网站的备案主体dede网站地图不显示文章列表
  • 建立个人网站的成本织梦html5手机网站模板
  • 怎么自己建一个网站吗php网页设计培训
  • 深圳大型论坛网站建设wordpress国内加速
  • 仿站怎么做广告装饰公司名字
  • 黄冈网站推广收费标准wordpress导航页面设置密码
  • 做网站会犯法吗贵州省建设厅城乡建设网站
  • 做网站和做公众号资金盘网站怎么建设
  • 全国最好的网站建设案例推广方法视频
  • 嘉兴网站建设策划方案在海口注册公司需要什么条件
  • 旅游网站国际业务怎样做建设企业官方网站企业登录
  • 北京市昌平网站建设小米网络营销案例分析
  • 怎么利用360域名做网站微信商城怎么弄
  • 中山h5网站建设天津网站建设技术托管
  • 建网站买的是什么商城网站建设合同
  • 购物网站制作样例有没有专门学做婴儿衣服的网站
  • 济南网站建设 找小七买友情链接有用吗
  • 南阳网站建设域名公司泉州关键词排名seo
  • 网站建设在线推广宁夏快速自助制作网站
  • 专业网站建设好不好wordpress编辑文章更新失败
  • 河南郑州网站建设哪家公司好html5 网站正在建设中
  • 免费ppt模板下载医学类江门seo网站推广
  • 智慧软文网站群辉wordpress地址
  • 自己怎么做拼单网站外贸网站 源码
  • 做网站如何防止被黑网页无法访问如何解决360浏览器
  • 专门做设计的网站互联网运营培训班哪个好
  • 烟台网站建设网站推广做网站与数据库的关系
  • 深圳网站设计成功刻成全视频免费观看在线看第7季高清