我正在写一个聊天应用程序。我使用while(true)
无限循环来允许应用程序通过控制台和来自Socket
的输入不断地“监听”用户输入。无限循环显然不是实现这一目标的最佳方式 - 毫不奇怪,在程序运行仅约一分钟后(我的计算机粉丝尖叫),我得到OutOfMemoryError: Java Heap space
。
我的问题是:如果不是通过一个无限循环,我怎样才能不断修改我的程序(或至少以小间隔修改,比如每秒一次)检查输入源,响应,然后再回到检查? / p>
代码(带有一些注释)如下:
import java.io.*;
import java.net.*;
public class Main {
public static void main(String[] args) throws IOException, ConnectException {
ServerSocket receiveServerSocket = new ServerSocket(Integer.parseInt(args[0])); // args contains two port numbers
Socket sendSocket;
while(true) { // note - I use the exact same infinite loop strategy here, except in this case an OutOfMemoryError is not thrown
try {
sendSocket = new Socket(InetAddress.getLocalHost(), Integer.parseInt(args[1]));
break;
} catch (ConnectException e) {}
}
DataOutputStream os = new DataOutputStream(sendSocket.getOutputStream());
Socket receiveSocket = receiveServerSocket.accept();
DataInputStream is = new DataInputStream(receiveSocket.getInputStream());
BufferedReader input = new BufferedReader (new InputStreamReader(System.in));
String message;
while(true) { // Here's the infinite loop in question
if(input.ready()) { // "checks" to see if the user has entered text
message = input.readLine(); // responds
os.writeInt(message.getBytes().length);
os.writeBytes(message);
}
if(is.available() > 0) { // checks to see if Socket has received text
byte[] bytes = new byte[is.readInt()]; // responds (Incidentally, this is the specific line where the OutOfMemoryError occurs)
is.read(bytes,0,bytes.length);
System.out.println(new String(bytes,0,bytes.length,"UTF-8"));
}
}
}
}
由于
答案 0 :(得分:1)
尝试打印is.readInt()
的值。您可能正在读取垃圾值并尝试分配导致OutOfMemoryError的大量内存。
同时将while循环放在一个线程中并调用Thread.sleep(1000)
以1秒为间隔进行定期检查。
答案 1 :(得分:1)
我的一些观察结果:
答案 2 :(得分:1)
有两个问题。
(1)您需要更改
os.writeBytes(message);
到
os.write(message.getBytes(), 0, message.getBytes().length);
原因是writeBytes
丢弃了每个String
的一个字节。来自Javadoc -
将字符串作为序列写入基础输出流 字节。字符串中的每个字符按顺序写出 丢弃其高八位。如果没有抛出异常,则为计数器 写入增加s的长度。
这当然的结果是你写的字节数实际上是你调用writeInt
时指定的字节数的一半。
(2)如果字节序列以数字字符开头,则应在调用writeInt
后编写某种分隔符,如空格。否则,对readInt
的调用可能会从流中读取错误的数字。
答案 3 :(得分:0)
你的第一个while循环实际上并不是一个循环,因为它在将一个值分配给sentocket之后就会中断。
也许你的应用程序有一个标志,如
bool isRunning=true;
你可以做到,
while(isRunning)
当你的申请被关闭时,它会改变isRunning = false,&踢出循环。