gpt4 book ai didi

java - 为什么 Collections#shuffle 不使用 ThreadLocalRandom?

转载 作者:搜寻专家 更新时间:2023-11-01 03:16:13 26 4
gpt4 key购买 nike

public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}

private static Random r;

我注意到 Collections#shuffle 使用 new Random() 而不是 ThreadLocalRandom.current(),我很好奇为什么。我写了一个比较两者的基准,使用 ThreadLocalRandom.current() 的方法每次迭代都更快。这是基准:

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 15, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(5)
public class MyBenchmark {
@Param({"10", "1000", "100000"})
private int i;

private List<Integer> list;

private static final Random RANDOM = new Random();

@Setup
public void initialize() {
list = ThreadLocalRandom.current()
.ints(i)
.boxed()
.collect(Collectors.toList());
}

public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}

@Benchmark
public List<Integer> oldMethod() {
Collections.shuffle(list, RANDOM);
return list;
}

@Benchmark
public List<Integer> newMethod() {
Collections.shuffle(list, ThreadLocalRandom.current());
return list;
}
}

结果:

Benchmark                 (i)  Mode  Cnt        Score       Error  Units
MyBenchmark.newMethod 10 avgt 100 60.802 ± 0.785 ns/op
MyBenchmark.newMethod 1000 avgt 100 6879.496 ± 15.638 ns/op
MyBenchmark.newMethod 100000 avgt 100 1248858.889 ± 33632.559 ns/op
MyBenchmark.oldMethod 10 avgt 100 90.636 ± 1.379 ns/op
MyBenchmark.oldMethod 1000 avgt 100 9740.442 ± 57.373 ns/op
MyBenchmark.oldMethod 100000 avgt 100 1511428.034 ± 27744.775 ns/op

那么,为什么 new Random() 而不是 ThreadLocalRandom.current()

我的猜测:

  • 自从JDK 1.7 中的ThreadLocalRandom 发布以来,该方法没有更新过
  • new Random() 用于线程安全?

最佳答案

Collections.shuffle(List)Collections.shuffle(List, Random) 方法是在 JDK 1.2 中添加的,而 ThreadLocalRandom直到 Java 7 才添加类。因此,对于 Java 7 之前的所有版本,shuffle(List) 使用 Random 的实例。

虽然未指定 shuffle(List) 的随机源,但它可能是行为上的意外变化,因为它被更改为使用不同的随机源。因此,该方法保持原样,使用 Random 的实例。

没有必要改变它。其他随机源,例如 ThreadLocalRandomSecureRandom,是 Random 的子类,它们可用于使用双参数重载进行洗牌shuffle(List, Random) 如果这是应用程序需要的。

关于java - 为什么 Collections#shuffle 不使用 ThreadLocalRandom?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50788378/

26 4 0
文章推荐: java - 为什么使用基类作为方法引用会导致编译器错误
文章推荐: java.lang.ArrayStoreException : when assigning value with incorrect type to Object[] array 异常
文章推荐: java - Micrometer - Prometheus Gauge 显示 NaN
文章推荐: java - Oracle 的 Collection 教程令人困惑