3

これは、Javaクラスの記述とそれらがどのようにインスタンス化されるかについての一般的な質問です。

public class transaction
{
    int amount;
    char ref;
}

クラスがこのように記述されている場合は、構造体のように使用できます。次に、データがデータグラムのbyte []としてネットワークを経由すると、トランザクションオブジェクトに変換されます。これを行う1つの場所は、別のクラスにあります。たとえば、次のようになります。

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);
    ...
}

しかし、今はクラスのデータとメソッドを1か所にまとめたいので(おそらくそうあるべきですか?)、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);
    ...
}

表面的には、すべて以前と同じ効果があります。

私の質問は次のとおりです。fromByte(byte[] buf)トランザクションデータ(amountとref)に対する操作をクラスに追加すると、オブジェクトtransactionをインスタンス化するためのオーバーヘッドが変更されます。transactionネットワークから1秒あたり数百のトランザクションが発生した場合、fromByte(byte[] buf)メソッドをtransactionクラスに追加すると、クラスでインスタンス化されたときにdoStuff、以前よりも多くのオーバーヘッドが使用されることになります。言い換えると、クラスが生成するたびに(データセグメントの静的変数として)単にanintとaを生成するのではなく、ヒープ(データセグメントではなく)で生成され、さらにメソッドがスタックにプッシュされますそして、chardoStufffoofromByte(buf)transactionクラスは、データセグメントで自分自身を再帰的に再度呼び出します(静的変数)。..

まあそれは少し混乱しているようです。データとメソッドを同じクラスに入れて最大速度を維持するためのより良い方法はありますか?再帰変数呼び出しを乗り越えることができますか(fromByteメソッドはトランザクションオブジェクトを返し、「int / char」形式で問題ありません)コメントはありますか?:-)

4

2 に答える 2

1

これは buf の先頭から 2 回読み取ります。

    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();

トランザクション データ (amount および ref) に対する操作 fromByte(byte[] buf) をトランザクション クラスに追加すると、トランザクション オブジェクトをインスタンス化するためのオーバーヘッドが変わります。

毎回作成することbyte[]もオーバーヘッドです。ByteBuffer

つまり、doStuff クラスが foo を生成するたびに単純に int と char を (データ セグメントの静的変数として) 生成するのではなく、ヒープ (データ セグメントではなく) に生成し、さらに fromByte( buf) メソッドがスタックにプッシュされ、トランザクション クラスがデータ セグメントで再帰的に自身を呼び出します (静的変数)...

前述のように、オブジェクトの作成はtransactionオーバーヘッドのごく一部である可能性があります。たとえば、ソケットからの読み取りには、せいぜい 100 倍の時間がかかります。

まあ、それは少し混乱しているようです。データとメソッドを同じクラスに配置し、最大速度を維持するより良い方法はありますか?

を使用しないでくださいbyte[]。毎回新しいオブジェクトを作成したり、毎回ByteBuffer新しいtransactionオブジェクトを作成したりしないでください。これらのオブジェクトは、事前に作成することも、まったく作成しないこともでき、再利用できます。

たとえば、接続が確立されたとき (または接続がリサイクルされたとき) に1 つの直接ByteBuffer を作成し、メッセージをデコードして、次のようなリスナーを呼び出すことを検討してください。

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

このようにして、スタック上またはその他の場所にオブジェクトは作成されません。

この状況では、パフォーマンスのボトルネックは、この情報の処理方法に応じて、Socket からの読み取りになります。;)

于 2013-01-09T18:51:48.443 に答える
1

パフォーマンスに関して、2 つのアプローチの唯一の違いは、静的メソッドの呼び出しのコストです。これは非常に些細なコストであり、JIT コンパイラーによってさらに削減されます。

カプセル化に関しては、クラスの知識をtransactionクラスにdoStuff入れたいのか、それともバイトストリーム構造の知識をクラスに入れたいのかという問題がありますtransaction。どちらにせよ主張はあります。

于 2013-01-09T18:53:53.870 に答える