2013-04-02 23 views
12

我正在尋找跨多個線程使用(種子)Random對象,javadocs指出我ThreadLocalRandom看起來不錯,除了我不能設置種子,所以我不能確保不同線程或運行之間的一致性。有沒有辦法使用ThreadLocalRandom任何實際的原因還是會接受做一些這樣的:我應該比ThreadLocal更喜歡ThreadLocalRandom <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

你想在不同的線程中共享一個Random實例嗎?或者確保每個線程都有自己的Random實例? –

+0

根據「隨機」共享的文檔,線程之間的一個「隨機」對象是一個糟糕的主意。我只是想控制使用的隨機對象的種子,因此行爲是一致的和可重複的。 – dimo414

+0

你可以用反射注入一個種子(初始化爲false,setSeed並將初始化設置爲true)。 – assylias

回答

6

你可以簡單地使用Random,只要確保每個Random對象只在一個線程內被訪問。

Random,是一個古老的類如Vector,是不必要的嚴重同步。他們可能想要展示Java的線程支持,因爲那時它是一件大事。此外,Java主要用於運行大多數單處理器的消費類個人電腦,因此同步不會像今天在多處理器上那樣影響縮放。

現在一個明顯的答案是提供Random的線程不安全版本,就像提供線程不安全的ArrayList作爲Vector的替代方案。這沒有發生,相反,我們得到了ThreadLocalRandom。這有點奇怪,不知道背後的動機是什麼。在java8中,ThreadLocalRandom進一步優化爲直接在Thread對象中的某些int字段上進行操作。

1

code for ThreadLocalRandom似乎無論如何實現爲ThreadLocal(不完全像你所說的那樣,但可能接近足夠)。我認爲你有什麼將會很好。

+1

1.在Java 8中,ThreadLocalRandom的Thread中有指定的字段,所以ThreadLocal不再使用。 2.雖然使用ThreadLocal 確實消除了爭用,但在Random中仍然會有不必要的檢查。因此,它的性能不會與ThreadLocalRandom相媲美(即使在Java 7中)。 – kavinyao

+0

@kavinyao在java中無爭議的同步現在是相當快的。 –

0

首先,你的代碼對每個線程使用相同的種子。這可能是一個安全問題。此外,對Random實例成員的每次訪問都是同步的,因此它將比ThreadLocalRandom的相應方法(未同步)慢。 如果編譯器可以確定,那麼您的Random實例不會轉義當前的線程,它可以優化那些「同步」。但是由於您可以將共享引用存儲在ThreadLocal中,因此編譯器無法檢查它。

相關問題