Bir akış (veya paralel akış) oluşturmak ve bu akışını parçalarından birinde etkilemek için aynı Random
örneğini kullanmak güvenli midir?Rastgele ve Rastgele eşzamanlılıktan IntStream
Aşağıdaki kodu dikkate alın. Aynı gen
, paralel bir IntStream
oluşturmak ve her birkaç karakterde rastgele bir alan oluşturmak için kullanılır. Başarılı bir şekilde çalışır ve tamamlanır, hiçbir istisna atılmaz.
Bu kod parçacığı güvenli midir? Görünen o ki, geçersiz (aralık dışı) karakter değerleri yoktur. Yöntemleri synchronized
olarak işaretlenmediğinden, Random
'un iç verilerini bozmaya çalışmalıyım, ama görünüşe göre bu durum böyle değil. Niye ya?
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==' '));
}
}
}
Paralel akışta 'limit'i kullanmanın bir performans felaketi için bir reçete olduğunu unutmayın. Ve burada gereksizdir, çünkü ['gen.ints (len, 'a', 'z')'] (http://docs.oracle.com/javase/8/docs/api/java/util/ Random.html # ints-long-int-int-) ilk etapta sonlu bir akış oluşturmak için. Ayrıca, yeni nesnelerin 'Yeni Karakter' aracılığıyla açık bir şekilde oluşturulması gereksizdir, otomatik kutlamanın doğru şeyi yapmasına izin verebilirsiniz. Ancak, ilk StringBuilder :: append 'dizgesini' StringBuilder :: appendCodePoint' olarak değiştirdiğinizde, hiç kutu kullanmanıza gerek yoktur, ancak 'IntStream' kullanarak her şeyi gerçekleştirebilirsiniz. – Holger
Bu arada, bağlı * özel *, yani 'z' dahil edilmek isteniyorsa, 'z' + 1 'öğesini bağlı olarak kullanmanız gerekir. → 'gen.ints (len, 'a', 'z' + 1) .parallel() haritası (i -> gen.nextDouble()
Holger
Bu arada, aşağıdakileri de basitleştirebilirsiniz:“ Assert.assertTrue (text.chars(). allMatch (c -> (c> = 'a' &&) c <= 'z') || c == '')); 'Assert.assertTrue (text.matches (" [az] * ")) ile aynıdır; ') – Holger