Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 来自随机和随机并发的IntStream_Java_Random_Concurrency_Java 8_Java Stream - Fatal编程技术网

Java 来自随机和随机并发的IntStream

Java 来自随机和随机并发的IntStream,java,random,concurrency,java-8,java-stream,Java,Random,Concurrency,Java 8,Java Stream,使用相同的Random实例生成流(或并行流)并在其中一个部分影响该流是否安全 考虑下面的代码。相同的gen用于生成并行IntStream,并每隔几个字符生成一个随机空间。它成功运行并完成,没有引发异常 但这段代码是线程安全的吗?看起来是这样,因为没有无效(超出范围)的字符值。我认为我应该破坏Random的内部数据,因为它的方法没有标记为synchronized,但显然不是这样。为什么? public class RandomGenTest { Random gen = new Rand

使用相同的
Random
实例生成流(或并行流)并在其中一个部分影响该流是否安全

考虑下面的代码。相同的
gen
用于生成并行
IntStream
,并每隔几个字符生成一个随机空间。它成功运行并完成,没有引发异常

但这段代码是线程安全的吗?看起来是这样,因为没有无效(超出范围)的字符值。我认为我应该破坏
Random
的内部数据,因为它的方法没有标记为
synchronized
,但显然不是这样。为什么?

public class RandomGenTest {

    Random gen = new Random();

    String getRandomText(int len, double spaceProb) {
        return gen.ints(len, 'a', 'z'+1)
                    .map(i-> gen.nextDouble()<spaceProb?' ':i)
                    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
    }

    @Test
    public void test() {
        for (int a=10000; a<10000000; a*=2) {
            String text = getRandomText(a, .2);
            Assert.assertTrue(text.chars().allMatch(c -> (c>='a' && c<='z') || c==' '));
        }
    }

}
公共类随机测试{
Random gen=新的Random();
字符串getRandomText(int len,双空格prob){
返回gen.ints(长度'a',z'+1)
.map(i->gen.nextDouble()='a'和&c
随机

Auv.Read的实例是线程安全的。但是,跨线程同时使用相同的JavaUTIL随机实例可能会遇到争用,从而导致性能不佳。
Random
是一个线程安全的对象,因为
AtomicLong
保留了当前种子,因此使用它可以逆转大部分并行加速,这是您练习的重点

相反,请使用
ThreadLocalRandom.getCurrent()
并至少避免争用问题(尽管引入了
ThreadLocal
查找的开销)。还可以使用
SplittableRandom
检索外部随机数流。此实现允许对流元素进行随机访问,这是good并行化的关键

import static java.util.concurrent.ThreadLocalRandom.current;

String getRandomText(int len, double spaceProb) {
    return new SplittableRandom().ints(len, 'a', 'z'+1).parallel()
      .map(i -> current().nextDouble()<spaceProb ? ' ' : i)
      .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
导入静态java.util.concurrent.ThreadLocalRandom.current;
字符串getRandomText(int len,双空格prob){
返回新的SplittableRandom().int(len'a',z'+1).parallel()

.map(i->current().nextDouble())请注意,在并行流上使用
limit
会导致性能灾难。在这里没有必要,因为您可以首先使用它来构造有限流。此外,通过
new Character
显式创建新对象是没有必要的,您可以让自动装箱做正确的事情。但是当您更改首先
StringBuilder::append
StringBuilder::appendCodePoint
,您根本不需要装箱,只需使用
IntStream
即可执行所有操作。顺便说一句,绑定是独占的,因此如果您希望包含
'z'
,则必须使用
'z'+1
作为绑定。→ <代码>gen.ints(len,'a','z'+1).parallel().map(i->gen.nextDouble())顺便说一下,您还可以简化断言:
Assert.assertTrue(text.chars().allMatch(c->='a'&&c@Holger,限制()在这里不是灾难,因为
gen.ints('a','z')
返回一个无序流。
gen.ints(1_000_000,'a','z'+1)。parallel().toArray()
对我来说显示的性能与
gen.ints('a','z'+1).parallel().limit(1_000_000).toArray()一样差
。真正的问题是使用
Random
而不是
SplittableRandom
@Tagir Valeev:Random number generation通常不是一个便宜的操作,但我想强调的是,程序员应该避免在并行流上使用
limit
,特别是在有一个简洁的替代方法来构建一个fi的情况下首先是一条非常大的河流。它是关于(不)习惯它…