Java中的聊天系统

时间:2011-12-01 02:40:59

标签: java client-server

有没有办法立即打印从客户端收到的消息,而不使用无限循环来检查输入流是否为空? 因为我发现使用无限循环消耗了大量的系统资源,这使得程序运行得如此之慢。我们还必须在客户端执行相同(无限循环)以实时在屏幕上打印消息。 我正在使用Java。

6 个答案:

答案 0 :(得分:2)

您应该在单独的Thread中处理输入流 - 让它block等待输入。它阻止时不会使用任何资源。如果你在做这类事情时看到过多的资源使用,那你就错了。

答案 1 :(得分:0)

我认为你可以把你的循环放在一个不同的线程中,让它在迭代之间睡一会儿(可能是半秒?)。它仍然是一个无限循环,但它不会消耗几乎同样多的资源。

答案 2 :(得分:0)

有两种方法可以避免繁忙的循环/睡眠。

  • 为每个客户端连接使用一个线程,并让每个线程调用read。这会阻塞线程,直到客户端发送一些数据,但这没有问题,因为它不会阻塞处理其他客户端的线程。

  • 使用Java NIO频道选择器。这些允许线程等待,直到其中一个通道(在这种情况下是套接字)中有数据要读取。这里有Oracle Java Tutorials部分。

在这两种方法中,第二种方法在整体资源使用方面最有效。 (每个客户端的线程方法在线程堆栈上使用大量内存,在线程切换开销上使用CPU。)


重复调用(例如)InputStream.available()以查看是否有任何输入的繁忙循环非常低效。您可以通过使用Thread.sleep(...)调用减慢轮询速度来降低效率,但这会产生使服务响应速度降低的副作用。例如,如果在每组轮询之间添加1秒的睡眠,则每个客户端将看到的效果是服务器通常在处理每个请求之前延迟1秒。假设这些请求是击键并且响应回应它们,最终结果是一个非常滞后的服务。

答案 3 :(得分:0)

您不需要稍微更改架构以容纳WebSockets。看看Socket.IO。它是一个跨浏览器的WebSockets启用程序。

您必须编写将数据推送到客户端的控制器(例如在java中的servlet)。这不遵循请求 - 响应架构。

您还可以对其进行构建,以便“推送servlet”从客户端触发“请求”以获取“响应”。

由于您的问题涉及Java,如果您对WebSockets感兴趣,请查看此link

答案 4 :(得分:0)

如果你正在使用Sockets,那么你应该选择任何网络。

然后你可以使用你可以使用DataInputStream获得的套接字socket.getInputStream()(我认为这是正确的方法)并执行以下操作:

public DataInputStream streamIn;
public Socket soc;

// initialize socket, etc...
    streamIn = soc.getInputStream();

public String getInput() {
    return (String) streamIn.readUTF(); // Do some other casting if this doesn't work
}

streamIn.readUTF()阻止,直到数据可用,这意味着您不必循环,并且线程将允许您在等待数据时进行其他处理。

在此处查看有关DataInputStream的更多信息以及您可以使用它做些什么:http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html

答案 5 :(得分:0)

不需要线程的方法将涉及对输入流进行子类化并添加通知类型方法。当被调用时,该方法将警告任何感兴趣的对象(即,由于添加到流而必须改变状态的对象)已经进行了改变。然后,这些感兴趣的对象可以以任何方式响应。

写入缓冲区的对象将进行正常写入,之后将调用输入流上的notify()方法,通知所有感兴趣的对象。

编辑:这可能需要对几个类进行子类化,因此可能需要进行大量的代码更改。如果不了解您的设计,您将不得不决定实施是否值得付出努力。