gpt4 book ai didi

java - Java 17 中的线程安全随机生成器

转载 作者:行者123 更新时间:2023-12-05 09:27:01 26 4
gpt4 key购买 nike

Java 17 添加了一个新的 RandomGenerator 接口(interface)。然而,似乎所有的新实现都不是线程安全的。在多线程情况下使用新接口(interface)的推荐方法是使用 SplittableRandom 并在生成新线程时从原始线程调用 split。但是,在某些情况下,您无法控制生成新线程的代码部分,您只需要在多个线程之间共享一个实例。

我可以使用 Random 但这会导致争用,因为所有的同步。也可以使用 ThreadLocalRandom,但我不愿意这样做,因为这个类现在被认为是“legacy”,而且因为这没有给我一个线程安全的实现RandomGenerator 没有全部样板文件:

 new RandomGenerator() {

@Override
public int nextInt() {
return ThreadLocalRandom.current().nextInt();
}

@Override
public long nextLong() {
return ThreadLocalRandom.current().nextLong();
}

...
}

对我来说,这似乎是新 API 中一个相当根本的差距,但我可能遗漏了一些东西。获得 RandomGenerator 的线程安全实现的惯用 Java 17 方法是什么?

最佳答案

当您无法控制线程的工作拆分或创建时,从使用站点的角度来看,最简单的解决方案是 ThreadLocal<RandomGenerator> .

public static void main(String[] args) {
// spin up threads
ForkJoinPool.commonPool().invokeAll(
Collections.nCopies(8, () -> { Thread.sleep(300); return null; }));

doWork(ThreadLocal.withInitial(synching(SplittableGenerator.of("L32X64MixRandom"))));
doWork(ThreadLocal.withInitial(synching(new SplittableRandom())));
doWork(ThreadLocal.withInitial(ThreadLocalRandom::current));
}

static final Supplier<SplittableGenerator> synching(SplittableGenerator r) {
return () -> {
synchronized(r) {
return r.split();
}
};
}

private static void doWork(ThreadLocal<RandomGenerator> theGenerator) {
System.out.println(theGenerator.get().toString());
Set<Thread> threads = ConcurrentHashMap.newKeySet();
var ints = Stream.generate(() -> theGenerator.get().nextInt(10, 90))
.parallel()
.limit(100)
.peek(x -> threads.add(Thread.currentThread()))
.toArray();
System.out.println(Arrays.toString(ints));
System.out.println(threads.stream().map(Thread::getName).toList());
System.out.println();
}

由于这不会在将一个 RNG 移交给另一个线程之前拆分 RNG,而是从已经存在的工作线程中进行拆分,因此它必须同步操作。但是当第一次查询线程局部变量时,每个线程只发生一次。还值得注意的是,基础 RNG 只能从该同步块(synchronized block)访问。

请注意,这也允许集成旧版 ThreadLocalRandom.current()没有额外的同步。它甚至可以与 Random r = new Random(); doTheWork(ThreadLocal.withInitial(() -> r)); 这样的同步 RNG 一起使用.

当然,这只是为了说明,因为所讨论的 RNG 有专门的方法来创建流,这些流可以在工作负载移交给另一个工作线程之前进行拆分。

关于java - Java 17 中的线程安全随机生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73021220/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com