3

这是关于编写 java 类以及如何实例化它们的一般问题。

public class transaction
{
    int amount;
    char ref;
}

如果一个类是这样写的,那么它可以像结构一样使用。然后,当数据作为数据报中的 byte[] 通过网络传输时,它被转换为事务对象。这样做的一个地方是在一个单独的类中,这样说:

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

从表面上看,这一切都和以前一样。

我的问题是:fromByte(byte[] buf)将交易数据(金额和参考)的操作添加到transaction类中,然后实例化对象的开销transaction发生变化。如果每秒有数百个事务来自网络,那么将fromByte(byte[] buf)方法添加到transaction类意味着当它在doStuff类中实例化时,将使用比以前更多的开销。换句话说,不是每次生成类时简单地生成一个int和一个(作为数据段上的静态变量) ,而是在堆上生成它(我认为,而不是数据段),然后将方法推入堆栈然后chardoStufffoofromByte(buf)transaction类再次在数据段上递归调用自身(静态变量)......

好吧,这似乎有点乱。有没有更好的方法将数据和方法放在同一个类中并保持最大速度?它能否克服递归变量调用(fromByte 方法返回一个事务对象,在“int/char”形式中没问题)有什么意见吗?:-)

4

2 回答 2

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(byte[] buf) 添加到交易类之后,实例化交易对象的开销就会发生变化。

每次创建一个byte[]and也是一种开销。ByteBuffer

换句话说,每次 doStuff 类生成 foo 时,不是简单地生成一个 int 和一个 char (作为数据段上的静态变量),而是在堆上生成它(我认为,而不是数据段),然后是 fromByte( buf) 方法被推入堆栈,然后事务类再次在数据段上递归调用自身(静态变量)...

如前所述,创建transaction对象可能只是您开销的一小部分。例如,从 Socket 读取最多需要 100 倍的时间。

好吧,这似乎有点乱。有没有更好的方法将数据和方法放在同一个类中并保持最大速度?

不要使用byte[],不要ByteBuffer每次都创建一个新transaction对象,也不要每次都创建一个新对象。您可以提前或根本不创建这些对象并重新使用它们。

例如,考虑在建立连接(或回收一个)时创建一个直接ByteBuffer 并解码消息并调用一个监听器,如

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

这样就不会在堆栈上或其他地方创建任何对象。

在这种情况下,您的性​​能瓶颈将是从 Socket 读取,这取决于您如何处理这些信息。;)

于 2013-01-09T18:51:48.443 回答
1

在性能方面,这两种方法的唯一区别是调用静态方法的成本。这是一个非常微不足道的成本,并且通过 JIT 编译器进一步降低。

在封装方面,问题是你是想把类的知识放在transaction类中,doStuff还是把字节流结构的知识放在transaction类中。无论哪种方式都有一个论据。

于 2013-01-09T18:53:53.870 回答