我在Java中实现了简单的服务器 - 客户端聊天。这是服务器的源代码:
public class Server {
final private static int PORT = 50000;
private static class Read extends Thread {
private static Socket socket;
private static String address;
public Read(Socket socket) {
this.socket = socket;
address = socket.getInetAddress().toString().substring(1);
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while (true) {
msg = in.readLine();
if (msg == null) {
in.close();
return;
}
System.out.println(address + ": " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class Write extends Thread {
private static Socket socket;
public Write(Socket socket) {
this.socket = socket;
}
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String msg;
while (true) {
if (socket.isClosed()) {
out.close();
return;
}
if (stdin.ready()) {
msg = stdin.readLine();
out.println(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket;
boolean listening = true;
serverSocket = new ServerSocket(PORT);
while (listening) {
Socket socket = serverSocket.accept();
String address = socket.getInetAddress().toString().substring(1);
System.out.println("Connection Established " + address);
Thread read = new Read(socket);
Thread write = new Write(socket);
read.start();
write.start();
try {
read.join();
write.join();
} catch(InterruptedException e) {
}
socket.close();
System.out.println("Connection Closed " + address);
}
serverSocket.close();
}
}
工作正常,但有问题。对于每个已建立的连接,内存不断增长。我认为问题是为线程分配的内存后来没有释放,但我不太确定。我该如何解决这个问题?
编辑:客户端程序:
class Client {
final private static int PORT = 50000;
private static class Read extends Thread {
private Socket socket;
private String address;
public Read(Socket socket) {
this.socket = socket;
address = socket.getInetAddress().toString().substring(1);
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while (true) {
msg = in.readLine();
if (msg == null) {
System.out.println("Connection closed " + address);
System.exit(0);
}
System.out.println(address + ": " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class Write extends Thread {
private Socket socket;
public Write(Socket socket) {
this.socket = socket;
}
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Scanner sc = new Scanner(System.in);
String msg;
while (true) {
msg = sc.nextLine();
out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
PrintWriter out;
BufferedReader in;
Scanner sc = new Scanner(System.in);
while (true) { //for the test only
Socket socket = null;
try {
socket = new Socket("78.90.68.125", PORT);
} catch(java.net.ConnectException e) {
System.out.println("Connection error: host unreachable");
System.exit(1);
}
/*
String address = socket.getInetAddress().toString().substring(1);
System.out.println("Connection established " + address);
Thread read = new Read(socket);
Thread write = new Write(socket);
read.start();
write.start();
try {
read.join();
write.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
finally {
*/
socket.close();
// }
//System.out.println("Connection closed " + address);
}
}
}
答案 0 :(得分:4)
伊万,
与线程有关的一些事情。
永远不要这样做:
try {
read.join();
write.join();
} catch(InterruptedException e) {
}
总是在catch子句中添加一些内容,并将其作为log.error。你没有机会知道它发生了。
然后,所有流/关闭等必须进入finally块。否则你无法确保关闭所有必要的东西。
你可能想要重用连接。试试这个: http://commons.apache.org/pool/
您是否可以告诉我们您是否经常通过sysout关闭连接? 每次打开连接时以及每次关闭连接时,基本上都会尝试创建日志语句。可能你会看到你遗失的东西。
答案 1 :(得分:4)
尝试制作
private static class Read extends Thread {
private static Socket socket;
private static String address;
和
private static class Write extends Thread {
private static Socket socket;
非静态。
另外,我不知道你是如何检查内存的,但是要记住Java是垃圾收集的,你会看到最初的内存使用量增加,直到垃圾收集器(GC)收集它并再次增加直到下一次GC运行。所以它持续增长而没有任何下降很长时间只有内存泄漏,否则你很高兴。
我按原样运行上面的代码并运行了大约1-2个小时,在Mac机器上使用JDK 6的内存使用量大约为54MB。我没有使用jdk附带的JConsole
来查看mem用法。我发现没有问题。
下面是我在我的ans中提到的图表,你有峰值和下降..最后当我停止客户端它是平的。
答案 2 :(得分:2)
尝试将socket.close()放在 finally 块中,以确保它运行。
但我认为你的代码可能有更大的问题,因为你没有使用连接池,你不必要地打开新的连接。