2011-05-26 48 views
0

嗨,大家好,我有以下幾點。多線程頭痛。 Java的。返回值

class a extends Thread  
{ 
    public synchronized BigInteger getUniqueID() 
    { 
     BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase); 
     return aUniqueID; 
    } 
} 

class b extends a 
{ 
    public run() 
    { 
     BigInteger uniquieID = getUniqueID();  
     // store UniqueID in another database table with other stuff 
    } 
} 

而我得到的是存儲在數據庫表中的重複唯一標識。我假設因爲在這個多線程環境中uniqieID正在改變。

我明顯會在某個地方出現可怕的可怕錯誤,我猜我不應該以這種方式返回價值。或者應該根據getUniqueID方法的響應將uniqueID定義爲新的BigInteger。

任何幫助將不勝感激,因爲我脆弱的心靈已經被扭曲了!

乾杯

艾倫

+0

當你說「我得到的是錯誤的唯一ID存儲在某處」,你的意思是你重複?哪種方式是「錯誤的」? – stivlo 2011-05-26 09:24:58

+0

是的,抱歉,只是稍微修改了說明。我將unqiue ID存儲在數據庫表中,在這裏我有一些(但不是全部)重複出現。 – 2011-05-26 09:26:10

+1

什麼定義了UniqueKeyFromDatabase? – 2011-05-26 09:28:52

回答

2

BigInteger是(從JavaDocs

不可變的任意精度整數

所以這排除了任何突變該BigInteger的對象。我想看看getUniqueKeyKeyFromDatabase

+3

我也這麼想過。確認你是對的,看代碼我可以看到我做了什麼,我從現有表中選擇max,然後插入以創建一個新的唯一ID。但是返回之前發現的最大變量。如此愚蠢。非常感謝你! – 2011-05-26 09:31:28

2

您getUniqueKeyFromDatabase()必須將不返回相同的值的兩倍的方法。其他一切都無關緊要。

每個線程都有自己的局部變量副本,它們是不共享的。

順便說一句:不要延伸線程,它的不良做法往往會導致混淆。

+0

非常感謝Peter,在評論和Jeff的下面,我意識到我所做的一切。我正在返回我找到的最大ID,而不是新的唯一ID。真的很愚蠢的我:(我還需要閱讀爲什麼不擴展線程!再次感謝。 – 2011-05-26 09:35:00

+0

如果你一次在兩個線程中調用max,你仍然會得到兩次相同的值。我建議你重新思考你如何得到ids。 – 2011-05-26 10:00:17

+0

完成並完成!我現在正確地插入到表中,並在synchronized方法中返回新生成的密鑰。我應該怎麼處理? – 2011-05-26 10:03:06

1

你的問題是因爲你沒有真正同步任何東西。類A中的getUniqueID()方法在其自己的隱式監視器上同步。但是這意味着每次創建一個新線程時,都會自動同步每個線程。那有意義嗎 ?

您需要同步一些共享變量。說明這一點的一個快速修復(但實際上並未使用它)是:在下面的示例中,所有線程都在同一對象上進行同步(共享靜態)。

class A extends Thread { 

    static Object shared = new Object(); 

    public BigInteger getUniqueID() 
    { 
     synchronize (shared) { 
     BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase); 
     return aUniqueID; 
     } 
    } 

} 
0

很可能是​​修飾符getUniqueID()毫無意義,因爲您不修改任何狀態。它也不保護getUniqueKeyFromDatabase(),因爲它在實例上同步。這意味着每個線程都運行而不與其他線程同步。

你可以嘗試,如果

public BigInteger getUniqueID() { 
    synchronized (a.class) { 
     BigInteger aUniqueID = new BigInteger(getUniqueKeyFromDatabase); 
     return aUniqueID; 
    } 
} 

爲你工作好。如果是這樣,你應該考慮你的數據庫設計(或者在getUniqueKeyFromDatabase中發生的任何事情)。同步應該由數據庫完成,而不是在客戶端代碼中完成。

0

您必須對返回唯一標識的方法有問題。爲了確保每個對象的ids的唯一性,請使用類似於下面的內容,例如在您的課堂中。

PS:類名應以大寫字母開頭。也如@Peter Lawrey所建議的那樣實現Runnable,而不是擴展一個Thread。

private static int nextId = 0; 
    protected int id; 

    public a(){ 
     this.id = getNextId(); 
    } 
    private static int getNextId(){ 
     return nextId++; 
    }