Jac*_* G. 5 java random collections shuffle
public static void shuffle(List<?> list) {\n Random rnd = r;\n if (rnd == null)\n r = rnd = new Random(); // harmless race.\n shuffle(list, rnd);\n}\n\nprivate static Random r;\nRun Code Online (Sandbox Code Playgroud)\n\n我注意到Collections#shuffle使用new Random()而不是ThreadLocalRandom.current(),我很好奇为什么。我编写了一个基准测试来比较两者,并且使用的方法ThreadLocalRandom.current()每次迭代都更快。这是基准:
@State(Scope.Benchmark)\n@BenchmarkMode(Mode.AverageTime)\n@OutputTimeUnit(TimeUnit.NANOSECONDS)\n@Warmup(iterations = 15, time = 500, timeUnit = TimeUnit.MILLISECONDS)\n@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)\n@Fork(5)\npublic class MyBenchmark {\n @Param({"10", "1000", "100000"})\n private int i;\n\n private List<Integer> list;\n\n private static final Random RANDOM = new Random();\n\n @Setup\n public void initialize() {\n list = ThreadLocalRandom.current()\n .ints(i)\n .boxed()\n .collect(Collectors.toList());\n }\n\n public static void main(String[] args) throws Exception {\n org.openjdk.jmh.Main.main(args);\n }\n\n @Benchmark\n public List<Integer> oldMethod() {\n Collections.shuffle(list, RANDOM);\n return list;\n }\n\n @Benchmark\n public List<Integer> newMethod() {\n Collections.shuffle(list, ThreadLocalRandom.current());\n return list;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n结果:
\n\nBenchmark (i) Mode Cnt Score Error Units\nMyBenchmark.newMethod 10 avgt 100 60.802 \xc2\xb1 0.785 ns/op\nMyBenchmark.newMethod 1000 avgt 100 6879.496 \xc2\xb1 15.638 ns/op\nMyBenchmark.newMethod 100000 avgt 100 1248858.889 \xc2\xb1 33632.559 ns/op\nMyBenchmark.oldMethod 10 avgt 100 90.636 \xc2\xb1 1.379 ns/op\nMyBenchmark.oldMethod 1000 avgt 100 9740.442 \xc2\xb1 57.373 ns/op\nMyBenchmark.oldMethod 100000 avgt 100 1511428.034 \xc2\xb1 27744.775 ns/op\nRun Code Online (Sandbox Code Playgroud)\n\n那么,为什么new Random()使用 over呢ThreadLocalRandom.current()?
我的猜测:
\n\nThreadLocalRandom该方法自JDK 1.7发布以来就没有更新过new Random()用于线程安全?和方法是在 JDK 1.2 中添加的,而该类直到 Java 7 才添加Collections.shuffle(List)。因此,对于 Java 7 之前的所有版本,都使用.Collections.shuffle(List, Random)ThreadLocalRandomshuffle(List)Random
尽管未指定 的随机源shuffle(List),但将其更改为使用不同的随机源可能会导致行为发生意外变化。因此,该方法保持原样,使用 的实例Random。
没有太大必要改变它。其他随机源(例如ThreadLocalRandom和SecureRandom)是 的子类,如果应用程序需要的话,Random它们可以用于使用两个参数重载进行洗牌。shuffle(List, Random)