Apakah valid untuk membagikan satu instance Random
kelas di antara beberapa utas? Dan untuk menelepon nextInt(int)
dari beberapa utas secara khusus?
java.util.concurrent.ThreadLocalRandom
.
Apakah valid untuk membagikan satu instance Random
kelas di antara beberapa utas? Dan untuk menelepon nextInt(int)
dari beberapa utas secara khusus?
java.util.concurrent.ThreadLocalRandom
.
Jawaban:
Ini adalah utas aman dalam arti masih akan menghasilkan angka acak saat digunakan oleh banyak utas.
Implementasi Sun / Oracle JVM menggunakan sinkronisasi dan AtomicLong sebagai seed untuk meningkatkan konsistensi di seluruh thread. Namun tampaknya tidak dijamin di semua platform dalam dokumentasi.
Saya tidak akan menulis program Anda untuk meminta jaminan seperti itu, terutama karena Anda tidak dapat menentukan urutan nextInt()
pemanggilan.
Ini aman untuk benang, meskipun tidak selalu.
Lihat http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 untuk detail selengkapnya.
Menurut dokumentasi, Math.random () menjamin keamanannya untuk digunakan oleh banyak utas. Tetapi kelas Random tidak. Saya berasumsi bahwa Anda harus menyinkronkan itu sendiri.
Ya, Acak aman untuk thread. yang nextInt()
metode memanggil dilindungi next(int)
metode yang menggunakan AtomicLong seed, nextseed
(atom panjang) untuk menghasilkan benih berikutnya. AtomicLong
digunakan untuk keamanan benang pada generasi benih.
Seperti yang dikatakan, ini adalah penyimpanan utas, tetapi mungkin bijaksana untuk menggunakan java.util.concurrent.ThreadLocalRandom
menurut artikel ini (tautan mati). ThreadLocalRandom juga merupakan subkelas dari Random, sehingga kompatibel dengan versi sebelumnya.
Artikel ini linked dibandingkan profil hasil dari kelas Acak berbeda:
java.util.Random
,java.util.concurrent.ThreadLocalRandom
danjava.lang.ThreadLocal<java.util.Random>
. Hasil penelitian menunjukkan, bahwa penggunaan ThreadLocalRandom paling berkinerja, diikuti oleh ThreadLocal dan Random berkinerja terburuk itu sendiri.
Tidak ada alasan mengapa beberapa utas tidak dapat menggunakan semua Acak yang sama. Namun, karena kelas tersebut tidak secara eksplisit aman untuk thread dan mempertahankan urutan nomor pseudo-random melalui seed. Beberapa utas mungkin berakhir dengan nomor acak yang sama. Akan lebih baik untuk membuat beberapa Random untuk setiap utas dan menyemainya secara berbeda.
EDIT : Saya baru saja memperhatikan bahwa implementasi Sun menggunakan AtomicLong jadi saya rasa itu aman untuk Thread (seperti juga dicatat oleh Peter Lawrey (+1)).
EDIT2 : OpenJDK juga menggunakan AtomicLong untuk benih. Seperti yang dikatakan orang lain meskipun masih tidak baik untuk mengandalkan ini.
Inilah cara saya menangani masalah tanpa mengasumsikan bahwa Random menggunakan variabel atom. Itu masih bisa bertabrakan secara acak jika currentTime * thread id
sama di masa depan, tapi itu cukup langka untuk kebutuhan saya. Untuk benar-benar menghindari kemungkinan tabrakan, Anda dapat meminta setiap permintaan menunggu stempel waktu jam yang unik.
/**
* 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)
sebagian penting?
(24*60*60*1000)
agar utas dengan ID 12
di xxxxxxxxxx045
millis tidak diunggulkan sama dengan utas 22
di xxxxxxxxxx035
millis. Namun, saya tidak memiliki alasan kuat untuk menganggap bahwa ID utas adalah tambahan, dan tidak ada alasan kuat untuk berpikir saya membuat utas pada waktu yang lebih acak besok daripada hari ini. Saya menyederhanakan alg sekarang dan memperbarui deskripsi untuk mengidentifikasi kekurangannya.
The Random
kelas tidak diatur untuk satu contoh yang akan digunakan dalam beberapa thread. Tentu saja, jika Anda melakukan ini, kemungkinan besar Anda akan meningkatkan kemungkinan menjadi tidak dapat diprediksi dan mendekati angka acak . Tetapi karena ini adalah generator pseudo-random, saya tidak mengerti mengapa Anda perlu membagikan sebuah instance. Apakah ada persyaratan yang lebih spesifik?