我想知道用户是否使用BufferedReader中的readline方法发送了文本。当用户没有发送任何内容时,线程会保持睡眠状态。有没有办法做到这一点?我已经尝试了很长时间,但还没有成功..我想我必须认识到是否按下了一个ENTER键..但我知道如何做到这一点..我的程序界面是控制台.. < / p>
问题是:我有一个客户端 - 服务器程序。当客户端输入消息时,该消息会在另一个用户/客户端的屏幕上提示。但是,如果用户在10秒内没有发送消息,我想在屏幕上显示一条消息。所以我有一个Thread.sleep(1000)。问题是我不知道何时唤醒线程。
while((mensagem == null) || (!mensagem.trim().equals(""))) {
Thread.sleep(10000);
sendToAll(output, "[Your turn] ", "");
mensagem = input.readLine();
}
最后一行也不正确,因为我不想强迫用户输入,这样我就强迫了,因为我停在input.readLine()上。
解: 我使用setSoTimeout(10000)方法解决了这个问题。这是代码:
public Server(Socket socket) throws SocketException{
this.connection = socket;
this.connection.setSoTimeout(10000);
}
public void run(){
[...]
while((msg != null) && !(msg.trim().equals(""))){
try{
msg = input.readLine();
sendToAll(output, ": ", msg);
} catch (SocketTimeoutException e) {
sendToAll(output, "Time out ", "");
}
}
谢谢大家的想法!! :)
答案 0 :(得分:2)
你读完这样的整行:
String in;
while ((in = br.readLine()) != null) {
// If this is triggered, in contains a whole line and if the input came from console that means enter was pressed
}
修改:回复您的修改:
input.readLine()
是一种阻止方法。它将继续尝试读取整行,直到收到一行,抛出异常或达到EOF。您的问题是您需要10秒超时。如果我错了,请纠正我。
执行此操作的方法是创建一个计时器或未被调用阻止中断.readLine()调用的线程。您应该已经在其自己的线程中拥有所有I / O,因此从另一个线程(主线程或使用Timer)您需要创建一个将中断被阻塞线程的定时事件。使用Timer的示例,在循环之前添加此项:
java.util.Timer t = new java.util.Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
IOHandlerClass.this.interrupt();
}
}, 10000);
将IOHandlerClass替换为此代码所在类的名称(您没有发布代码,因此我不知道名称)。
现在,这将导致在10秒后抛出InterruptException,除非您停止计时器。因此,使用try-catch包围您的代码以捕获该异常,如果它被抛出则显示错误消息。如果在10秒内超时内获得有效响应,请记得取消计时器。
答案 1 :(得分:1)
您需要了解Java端和控制台端的内容。
在Java方面,readLine()
调用只是尝试读取字符,直到它看到有效的“行尾”序列,即输入流的结尾。这是一个阻塞调用,无法在您正在使用的API中指定超时。
在控制台端,控制台正在监视键盘事件并将其累积在行缓冲区中:
详细信息取决于控制台程序以及用户如何配置它。但是,事实仍然是,在用户键入ENTER之前,不会将任何内容发送到将控制台连接到Java应用程序的“管道”。简而言之,Java应用程序将看不到任何内容。
这意味着Java应用程序无法判断用户是否正在键入。
那么Java应用程序可以做什么?
您可以使用Timer在几秒钟/几分钟后向阻塞的Java线程(执行readLine()
调用的线程)发送中断。这将导致readLine()
调用解除阻塞并抛出IOException。但是,这种方法存在问题:
在readLine()
调用完成后,计时器会触发一个潜在的竞争条件,并且中断将转到应用程序本身。这可能会导致问题,具体取决于应用程序对中断的作用。您应该能够使用readLine
调用返回时主线程设置的正确同步标志来避免这种情况。
目前尚不完全清楚,但有迹象表明,如果您在管道上获得中断,则底层通道会自动关闭。这意味着您无法要求用户提供更多输入。
第二种方法可能是将BufferedReader
/ readLine()
代码替换为使用NIO渠道选择器的代码。除此之外,Selector
允许您等待超时以使通道具有可读数据。然后,您需要在其上实现缓冲和readline。
如果您想知道用户是否在控制台上输入了,您需要将控制台置于非线路编辑模式。这不能用纯Java完成,但有第三方库可以做这种事情。