我正在使用 LibGDX,自从我开始使用这个库以来,我一直遵循他们的建议,并且从未在运行时使用池和成员变量创建新对象,以防止触发垃圾收集器。但是,当涉及到网络时,我很难在不创建新的 Data(Input/Output)Stream 对象的情况下从 InputStream 读取(并从 OutputStream 写入)。
我需要一种方法来使这些对象可重用,以防止每次收到玩家移动时创建新对象。 或者,我需要一种从输入/输出流中读取整数、 float 和 UTF 字符串而不使用此对象的方法。
目前,我的低效代码如下所示:
/**
* Represents a packet sent from client to server
* Used when a client sends a chat message to the server
* Created by winter on 25/03/16.
*/
public class PacketInChat extends Packet
{
private String message;
public PacketInChat() { }
public PacketInChat(String message) {
this.message = message;
}
@Override
public void readFrom(InputStream stream) throws IOException {
message = new DataInputStream(stream).readUTF(); //problem here
}
@Override
public void writeTo(OutputStream stream) throws IOException {
new DataOutputStream(stream).writeUTF(message); //problem here
}
//getters/setters for fields
}
我还通过读取它的名称来检测它是哪个套接字,因此这里也有问题:
String packetName = new DataInputStream(socket.getInputStream()).readUTF();
Packet packet = Pools.obtain((Class<? extends Packet>)Class.forName("package me.winter.socialplatformer.server.packet." + packetName));
packet.readFrom(socket.getInputStream());
有什么想法吗?谢谢
编辑:EJP 指出我无法在不创建新对象的情况下从 DataInputStream 读取字符串,因此我的示例几乎毫无用处。我设法在没有 DataInputStream 的情况下从字节中读取整数和浮点,并且我可以使用 StringBuffer (或 StringBuilder)读取字符串,但我必须进行这种优化的唯一重要情况是在 Player 移动的数据包中,其中不包含任何字符串。我还通过读取 id 而不是名称来从枚举中获取数据包类型,因此不再有问题。
但是,我仍然对如何重用 DataInputStream/DataOutputStream 感到好奇,并且会接受可以解释如何执行此操作的答案。
最佳答案
根据我的评论,只需使用 WeakHashMap<InputStream, DataInputStream>
,对于输出流也类似:
public class PacketInChat extends Packet
{
private Map<InputStream, DataInputStream> map = new WeakHashMap<>();
private String message;
public PacketInChat() { }
public PacketInChat(String message) {
this.message = message;
}
@Override
public void readFrom(InputStream stream) throws IOException {
DataInputStream din;
synchronized (map)
{
if ((din = map.get(stream)) == null)
{
map.put(din, in = new DataInputStream(stream));
}
}
message = din.readUTF();
}
}
输出也类似。 WeakHashMap
将确保数据流在其包装的流消失时被释放。
或者只是重组:
public class PacketInChat
{
DataInputStream din;
DataOutputStream dout;
public PacketInChat(InputStream in, OutputStream out)
{
this.din = new DataInputStream(in);
this.dout = new DataOutputStream(out);
}
public String readMessage() throws IOException { return din.readUTF(); }
public int readInt() throws IOException { return din.readInt(); }
// etc
public void writeMessage(String msg) throws IOException
{
dout.writeUTF(msg);
}
// etc
}
这样您就可以为每个输入/输出流对创建其中一个,并将它们保存在映射中的某个位置。
关于java - 如何使用Input/OutputStream读取/写入数据而不创建新对象LibGDX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41150693/