Random
Birden çok iş parçacığı arasında sınıfın bir örneğini paylaşmak geçerli midir? Ve nextInt(int)
özellikle birden çok iş parçacığından aramak ?
java.util.concurrent.ThreadLocalRandom
.
Random
Birden çok iş parçacığı arasında sınıfın bir örneğini paylaşmak geçerli midir? Ve nextInt(int)
özellikle birden çok iş parçacığından aramak ?
java.util.concurrent.ThreadLocalRandom
.
Yanıtlar:
Birden çok iş parçacığı tarafından kullanıldığında rasgele sayılar üretmeye devam etmesi açısından iş parçacığı güvenlidir.
Sun / Oracle JVM uygulaması, iş parçacıkları arasında tutarlılığı iyileştirmek için çekirdek olarak senkronize edilmiş ve AtomicLong kullanır. Ancak dokümantasyondaki tüm platformlarda garanti edilmiyor gibi görünüyor.
Özellikle aranacak sırayı belirleyemediğiniz için programınızı böyle bir garanti gerektirecek nextInt()
şekilde yazmazdım.
Her zaman olmasa da iş parçacığı güvenlidir.
Daha fazla ayrıntı için http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 adresine bakın.
Belgelere göre Math.random () , birden çok iş parçacığı tarafından kullanım için güvenli olduğunu garanti eder. Ancak Random sınıfı bunu yapmaz. O zaman bunu kendiniz senkronize etmeniz gerektiğini varsayıyorum.
Evet, Random iş parçacığı açısından güvenlidir. nextInt()
yöntem korumalı çağrıları next(int)
kullanan yöntem AtomicLong seed, nextseed
(uzun atom) bir sonraki tohum üretmek için. AtomicLong
tohum üretiminde iplik güvenliği için kullanılır.
Söylendiği gibi, bu iş parçacığı tasarrufu, ancak bu makaleyejava.util.concurrent.ThreadLocalRandom
göre kullanmak akıllıca olabilir (bağlantı ölü). ThreadLocalRandom ayrıca Random'ın bir alt sınıfıdır, bu nedenle geriye dönük olarak uyumludur.
Ürün farklı Rastgele sınıfların sonuçları profilleme karşılaştırıldı bağladığını:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
vejava.lang.ThreadLocal<java.util.Random>
. Sonuçlar, ThreadLocalRandom kullanımının en yüksek performanslı olduğunu, bunu ThreadLocal ve en kötü performans gösteren Random'ın izlediğini gösterdi.
Birden fazla iş parçacığının hepsinin aynı Random'ı kullanmaması için hiçbir sebep yok. Bununla birlikte, sınıf açıkça iş parçacığı güvenli olmadığından ve tohum aracılığıyla sözde rasgele sayıların bir dizisini koruduğundan. Birden çok iş parçacığı aynı rasgele sayı ile bitebilir. Her iş parçacığı için birden çok Rastgele oluşturmak ve bunları farklı şekilde tohumlamak daha iyi olacaktır.
DÜZENLE : Sun uygulamasının AtomicLong kullandığını yeni fark ettim, bu yüzden sanırım bu İş Parçacığı için güvenli (Peter Lawrey (+1) tarafından da belirtildiği gibi).
EDIT2 : OpenJDK da tohum AtomicLong kullanır. Başkalarının da söylediği gibi buna güvenmek hala iyi değil.
Random'ın atomik değişkenleri kullandığını varsaymadan problemi şu şekilde ele aldım. currentTime * thread id
Gelecekte bir süre eşitse yine de rastgele çarpışabilir , ancak bu benim ihtiyaçlarım için yeterince nadirdir. Çarpışma olasılığından gerçekten kaçınmak için, her isteğinizin benzersiz bir saat zaman damgası beklemesini sağlayabilirsiniz.
/**
* Thread-specific random number generators. Each is seeded with the thread
* ID, so the sequence of pseudo-random numbers are unique between threads.
*/
private static ThreadLocal<Random> random = new ThreadLocal<Random>() {
@Override
protected Random initialValue() {
return new Random(
System.currentTimeMillis() *
Thread.currentThread().getId());
}
};
(24*60*60*1000)
Kısmen önemli mi?
(24*60*60*1000)
Kimliğine sahip bir iplik böylece oldu 12
en xxxxxxxxxx045
milisaniye bir iş parçacığı aynı seribaşı alamadım 22
de xxxxxxxxxx035
milisaniye. Ancak iş parçacığı kimliklerinin artımlı olduğunu varsaymak için iyi bir nedenim yok ve yarın bugün olduğundan daha rastgele zamanlarda ileti dizileri oluşturduğumu düşünmek için iyi bir neden yok. Şimdi alg'ı basitleştirdim ve eksikliği belirlemek için açıklamayı güncelledim.
Random
Sınıf birden çok iş parçacığı kullanılmak üzere bir örneği için ayarlanmamış. Tabii ki, bunu yaptıysanız, muhtemelen tahmin edilemez ve rastgele sayılara yaklaşma olasılığınızı artıracaksınız . Ancak sözde rastgele bir üretici olduğu için neden bir örneği paylaşmanız gerektiğini anlayamıyorum. Daha spesifik bir gereklilik var mı?