有没有办法立即打印从客户端收到的消息,而不使用无限循环来检查输入流是否为空? 因为我发现使用无限循环消耗了大量的系统资源,这使得程序运行得如此之慢。我们还必须在客户端执行相同(无限循环)以实时在屏幕上打印消息。 我正在使用Java。
答案 0 :(得分:2)
答案 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()方法,通知所有感兴趣的对象。
编辑:这可能需要对几个类进行子类化,因此可能需要进行大量的代码更改。如果不了解您的设计,您将不得不决定实施是否值得付出努力。