2014-01-24 64 views
0

我想並行化一些代碼,它使用「常量」類中的靜態字段。在目前的代碼基本是這樣的用Java爲每個線程創建一個實例字段

public class myClass{ 

    public class Constants{ 
      public static int constant; 
    } 


    public static void main(String[] args){ 
      for(int i = 0 ; i<10 ; i++){ 
       Constants.constant = i; 
       System.out.println(Constants.constant/2); 
      } 
    } 
} 

顯然循環內的代碼更加嚴重依賴於恆類,它本身要複雜得多。我想要做的是爲循環的每次迭代創建一個線程,並分別進行所有計算,同時控制線程數量(現在我正在使用一個簡單的信號量)。 現在很明顯在上面的代碼中,Constants類是在線程之間共享的,因此不能被每個線程更新而不更新所有的線程。

所以我的問題是:是否有無論如何使我的常量類能夠有一個實例爲每個線程,所有雖然能夠以靜態方式訪問其字段?

回答

0

你所描述的是一個本地:http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html。這是一件好事使用。然而,正如Affe指出的那樣,你不能在代碼中使用它,因爲只有一個類的實例和它的靜態成員(每個類加載器)。如果您的Constants類是可以並行構建好幾個副本的東西,然後將它們合併在一起,則應通過刪除「static」來使Constants.constant成爲實例變量。然後創建一個線程局部MyClass中,像這樣:

private ThreadLocal<Constants> constants = new ThreadLocal<Constants> { 
    @Override protected Integer initialValue() { 
     return nextId.getAndIncrement(); 
    } 
} 

一旦你的線程完成更新他們的本地對象,就可以把它們粘到共享ArrayBlockingQueue。您的主線程可以將它們全部出列並按照您的願望合併它們。

另一件需要注意的事情是,如果您的迭代次數可能會變化很多,但您不想要那麼多,您可能希望在循環的每次迭代中使用線程池執行程序而不是一個線程線程。 (創建線程代價高昂,許多併發線程佔用內存和操作系統調度資源。)

+0

不是。如果他將值存儲在靜態字段中,則每個類加載器仍然只有一個值。 – Affe

+0

是的,你是對的。我沒有注意到這一點。讓我編輯答案... – snoopy

+0

展望ThreadLocal;基本上每次迭代都需要很多資源,它完全消耗了它所在的vcpu,所以我真的只需要每個vcpu(大約)一個線程。因此,一次只能運行很少的線程,並且在每次迭代的運行時和內存使用情況下,開銷將可以忽略不計。 –

相關問題