2013-04-02 6 views
12

Szukam użyć (zaszczepione) Random obiektów w wielu wątków, a javadocs wskazał mi ThreadLocalRandom, który wygląda świetnie, z wyjątkiem nie mogę ustawić materiału siewnego, więc nie mogę zapewnić spójności między różnymi wątkami lub uruchomień. Czy istnieje jakiś praktyczny powód, aby korzystać ThreadLocalRandom lub byłoby dopuszczalne zrobić coś jak następuje:Czy preferuję ThreadLocalRandom nad ThreadLocal <Random>?

// Pass returned ThreadLocal object to all threads which need it 
public static ThreadLocal<Random> threadRandom(final long seed) { 
    return new ThreadLocal<Random>(){ 
     @Override 
     protected Random initialValue() { 
      return new Random(seed); 
     } 
    }; 
} 
+1

Czy chcesz udostępnić jedną przypadkową instancję między różnymi wątkami? Lub upewnij się, że każdy wątek ma własną instancję Random? –

+0

Zgodnie z dokumentacją dla 'losowego' dzielenia jeden obiekt' losowy' między wątkami jest kiepskim pomysłem. Po prostu chcę kontrolować nasienie losowych obiektów, które są używane, więc zachowanie jest spójne i powtarzalne. – dimo414

+0

Można wstrzyknąć ziarno z odbiciem (zestaw zainicjalizowany na wartość false, wywołanie setSeed i zestaw z powrotem ustawiony na true). – assylias

Odpowiedz

6

Możesz po prostu użyć Random, upewnij się tylko, że każdy obiekt Random jest dostępny tylko w jednym wątku.

Random, będąc klasą starożytną, taką jak Vector, jest niepotrzebnie mocno zsynchronizowany. Prawdopodobnie chcieli pokazać wsparcie dla Javy, ponieważ była to wielka sprawa w tym czasie. Również Java była przeznaczona głównie do komputerów osobistych, które w większości miały jeden procesor, więc synchronizacja nie miała wpływu na skalowanie, tak jak ma to miejsce obecnie w przypadku wieloprocesorowych.

Teraz oczywistą odpowiedzią jest dostarczenie niebezpiecznej dla wątków wersji Random, podobnie jak dostarczenie wątku-unsfae ArrayList jako alternatywy dla Vector. Tak się nie stało, zamiast tego dostaliśmy ThreadLocalRandom. To trochę dziwne, nie jestem pewna, na czym polega motywacja. W java8, ThreadLocalRandom jest dodatkowo zoptymalizowany do działania bezpośrednio na niektórych polach int obiektu Thread.

1

code for ThreadLocalRandom wydaje się być realizowany jako ThreadLocal mimo to (nie dokładnie jakbyś umieścić go, ale prawdopodobnie blisko dość). Myślę, że to, co masz, będzie dobrze działać.

+1

1. W języku Java 8 istnieją wyznaczone pola w wątku dla ThreadLocalRandom, więc ThreadLocal nie jest już używany. 2. Podczas korzystania z ThreadLocal eliminuje rywalizację, niepotrzebne sprawdzanie jest nadal włączone w trybie losowym. Dlatego jego wydajność nie byłaby porównywalna z ThreadLocalRandom (nawet w Javie 7). – kavinyao

+0

@kavinyao synchronizacja bez synchronizacji w Javie jest dość szybka w tych dniach. –

0

Po pierwsze, twój kod używa tego samego materiału siewnego dla każdego wątku. To może być problem z bezpieczeństwem. Co więcej, każdy dostęp do członka twojej instancji Random jest zsynchronizowany, więc będzie wolniejszy niż odpowiednie metody ThreadLocalRandom (które nie są zsynchronizowane). Jeśli kompilator może mieć pewność, że instancja Przypadkowa nie ucieknie od bieżącego wątku, może zoptymalizować te "zsynchronizowane". ale Ponieważ możesz przechowywać wspólne odniesienia w ThreadLocal, kompilator nie może tego sprawdzić.

Powiązane problemy