2013-01-09 57 views
3

這是一個關於編寫java類以及它們是如何實例化的常見問題。java類的寫作和對象構造

public class transaction 
{ 
    int amount; 
    char ref; 
} 

如果一個類是這樣寫的,那麼它可以像結構一樣使用。然後,當數據通過網絡以數據報中的字節[]傳輸時,它會被轉換爲事務對象。一個地方做,這是一個單獨的類,這樣說:

public class doStuff 
{ 
    static transaction t; // the int and the char are alloc'd onto the DataSegment 

    public static transaction fromByte(byte[] buf) 
    { 
     t = new transaction(); // make sure t is null to begin with (on the heap) 
     t.ref = ''; // initialise char (to avoid null bytes) 

     t.amount = ByteBuffer.wrap(buf).getInt(); 
     t.ref = ByteBuffer.wrap(buf).getChar(); 

     return t; 
    } 
} 

然後另一個類調用doStuff像這樣:

import doStuff;  

class otherClass extends Thread 
{ 
    static transaction x = new transaction(); 

    ... in the run method 
    x = doStuff.fromByte(buf); 
    ... 
} 

但現在我想的類數據和方法保持在一起一個地方(據推測它應該是這樣的?),所以不要在doStuff類中使用fromByte(byte [] buf)方法,而是將它移到事務類中。因此,交易類現在看起來是這樣的:

public class transaction 
{ 
    int amount; 
    char ref; 

    static transaction t; 

    public static transaction fromByte(byte[] buf) 
    { 
     t = new transaction(); // make sure t is null to begin with 
     t.ref = ''; // initialise char (to avoid null bytes) 

     t.amount = ByteBuffer.wrap(buf).getInt(); 
     t.ref = ByteBuffer.wrap(buf).getChar(); 

     return t; 
    } 
} 

然後在otherClass我用:

import transaction; 

class otherClass extends Thread 
{ 
    static transaction x = new transaction(); 

    ... in the run method 
    x = fromByte(buf); 
    ... 
} 

,表面上一切如故有同樣的效果。

我的問題是:在將事務數據(金額和ref)上的操作fromByte(byte[] buf)添加到transaction類中之後,實例化transaction對象更改的開銷。如果每秒有數百次交易來自網絡,那麼將fromByte(byte[] buf)方法添加到transaction類意味着當它在doStuff類中實例化時,將會有比以前更多的開銷。換句話說,而不是簡單地生成intchar(如在該數據段的靜態變量)它在堆上(我想,而不是將數據段)中產生的doStuff類生成foo然後每個時間和進一步fromByte(buf)方法被推入堆棧,然後transaction類再次在數據段上自動調用自身(一個靜態變量)...

好吧,它似乎有點亂。有沒有更好的方法把數據和方法放在同一個班,並保持最高速度?它可以通過遞歸變量調用(fromByte方法返回一個事務對象,這在'int/char'表單中可以)任何評論? :-)

+1

爲什麼創建「事務」的開銷發生了變化? –

+0

你的意思是說'事務t'是靜態的嗎? –

+0

好吧,這真的是一個問題...如果你添加一個方法到一個類,所以有類中的數據和方法,那麼當類實例化更多的東西發生在引擎蓋下,對吧? – rupweb

回答

1

這將從buf的開始處讀取兩次。

t.amount = ByteBuffer.wrap(buf).getInt(); 
    t.ref = ByteBuffer.wrap(buf).getChar(); 

我懷疑你的意思

ByteBuffer bb = ByteBuffer.wrap(buf); 
    t.amount = bb.getInt(); 
    t.ref = bb.getChar(); 

已增加對交易數據的操作fromByte(字節[] buf中)(量和REF)爲交易類然後將塔頂的實例化交易對象的變化。

每次創建byte[]ByteBuffer也是開銷。

換句話說,而不是簡單地產生一個int和炭(如在該數據段的靜態變量)每個doStuff類生成富那麼它在堆上產生時間(我想,而不是將數據段)並且進一步fromByte(BUF)方法被壓入堆棧,然後將事務類再次調用自身遞歸上的數據段(一個靜態變量)...

如所提到的,在創建transaction obejct可能只是你開銷的一小部分。例如。從Socket讀取最多隻需要100倍。

好吧,它似乎有點亂。有沒有更好的方法把數據和方法放在同一個班,並保持最高速度?

不要使用byte[],不創建一個新的ByteBuffer每次不創建一個新的transaction對象每次。您可以預先創建這些對象,或根本不創建它們並重新使用它們。

例如考慮創建一個直接的ByteBuffer當連接建立(或循環的)和解碼該消息,並調用一個聽衆喜歡

interface TransactionListener { 
    public void onTransaction(int num, char status); 
} 

這樣沒有對象被創建,在堆棧上或除此以外。

在這種情況下,您的性​​能瓶頸將從Socket讀取,具體取決於您對此信息所做的操作。 ;)

+0

感謝您的幫助......以及我需要一個事務對象......(以及許多其他類型) ...將byte []傳遞給事務對象,然後ByteBuffer.wrap方法將其解包,不是嗎?如果我必須使用分佈式系統,有什麼比從套接字讀取更快的嗎? – rupweb

+0

好吧,我有雙重檢查,我沒有發現't.amount = ByteBuffer.wrap(buf).getInt(); t.ref = ByteBuffer.wrap(buf).getChar();'從buf的開頭讀取兩次...從我記得的getInt()方法讀取4個字節,然後將位置計數器增加4個字節那麼它的工作就是這樣! – rupweb

+0

我必須使用byte [],因爲這是通過網絡推送的! ...一個字節數組......但是,解碼消息並調用一個監聽器就是我正在努力實現的。我正在使用socket.read作爲監聽器......然後只是在做消息 – rupweb

1

就性能而言,這兩種方法之間的唯一區別是調用靜態方法的代價。這是一個非常微不足道的成本,並被JIT編譯器進一步降低。

在封裝方面,問題是您是否想將transaction類的知識放在doStuff類中,或者是否想將字節流結構的知識放入transaction類中。有兩種方法都有爭議。

+0

並且Peter Lawrey說這個程序的瓶頸是從插座,不會是其他成本。我的猜測是,如果字節流的東西只涉及事務數據,然後把它放在事務類中......但它似乎弄得一團糟...... – rupweb