하나의 인스턴스를 공유하는 것이 유효한가요? Random
여러 스레드간에 클래스 합니까? nextInt(int)
특히 여러 스레드에서 호출하려면 ?
java.util.concurrent.ThreadLocalRandom
있습니다.
하나의 인스턴스를 공유하는 것이 유효한가요? Random
여러 스레드간에 클래스 합니까? nextInt(int)
특히 여러 스레드에서 호출하려면 ?
java.util.concurrent.ThreadLocalRandom
있습니다.
답변:
여러 스레드에서 사용할 때 여전히 난수를 생성한다는 점에서 스레드로부터 안전합니다.
Sun / Oracle JVM 구현은 동기화 및 AtomicLong을 시드로 사용하여 스레드 간의 일관성을 향상시킵니다. 그러나 문서의 모든 플랫폼에서 보장되지는 않습니다.
특히 nextInt()
호출 될 순서를 결정할 수 없기 때문에 이러한 보증을 요구하도록 프로그램을 작성하지 않습니다 .
항상 그런 것은 아니지만 스레드로부터 안전합니다.
자세한 내용은 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6362070 을 참조하십시오.
문서에 따르면 Math.random () 은 여러 스레드에서 안전하게 사용할 수 있음을 보장합니다. 그러나 Random 클래스는 그렇지 않습니다. 그러면 직접 동기화해야한다고 생각합니다.
예, Random은 스레드로부터 안전합니다. 이 nextInt()
메서드 next(int)
는 AtomicLong seed, nextseed
(atomic long)을 사용하여 다음 시드를 생성하는 보호 된 메서드를 호출합니다 . AtomicLong
시드 생성시 스레드 안전성을 위해 사용됩니다.
말했듯이 스레드 저장이지만 이 기사 (링크 데드) java.util.concurrent.ThreadLocalRandom
에 따라 사용하는 것이 현명 할 수 있습니다 . ThreadLocalRandom은 Random의 하위 클래스이기도하므로 이전 버전과 호환됩니다.
링크 된 기사는 서로 다른 Random 클래스의 프로파일 링 결과를 비교했습니다 :
java.util.Random
,java.util.concurrent.ThreadLocalRandom
및java.lang.ThreadLocal<java.util.Random>
. 결과는 ThreadLocalRandom의 사용이 가장 성능이 뛰어나고 ThreadLocal이 그 다음으로 가장 성능이 좋지 않은 것으로 나타났습니다.
여러 스레드가 모두 동일한 Random을 사용할 수없는 이유는 없습니다. 그러나 클래스는 명시 적으로 스레드로부터 안전하지 않으며 시드를 통해 일련의 의사 난수를 유지합니다. 여러 스레드가 동일한 난수로 끝날 수 있습니다. 각 스레드에 대해 여러 개의 Random을 만들고 다르게 시드하는 것이 좋습니다.
편집 : 방금 Sun 구현이 AtomicLong을 사용하므로 스레드로부터 안전하다고 생각합니다 (Peter Lawrey (+1)도 언급했듯이).
EDIT2 : OpenJDK는 또한 시드에 AtomicLong을 사용합니다. 다른 사람들이 말했듯이 이것에 의존하는 것은 여전히 좋지 않습니다.
Random이 원자 변수를 사용한다고 가정하지 않고 문제를 처리 한 방법은 다음과 같습니다. currentTime * thread id
미래의 시간이 같으면 여전히 무작위로 충돌 할 수 있지만 내 필요에 따라 충분히 드뭅니다. 충돌 가능성을 진정으로 피하려면 각 요청이 고유 한 시계 타임 스탬프를 기다리도록 할 수 있습니다.
/**
* 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)
부분이 중요합니까?
(24*60*60*1000)
ID 12
를 xxxxxxxxxx045
가진 스레드 22
가 xxxxxxxxxx035
millis 의 스레드와 동일하게 시드되지 않도록하기위한 것 입니다. 그러나 스레드 ID가 증분이라고 가정 할 충분한 이유가 없으며 오늘보다 내일 더 임의의 시간에 스레드를 생성한다고 생각할 타당한 이유가 없습니다. 이제 alg를 단순화하고 단점을 식별하기 위해 설명을 업데이트했습니다.