如何实现超时的 Runnable?



我目前有一个相当简单的SSL服务器/客户端项目,涉及标准的Java后端和Android前端。我想在向客户端发送数据后尝试读取来自服务器的响应。但是,我遇到了一个小问题。服务器并不总是响应,所以我不得不以某种方式尝试以异步方式获得响应。(因为 read(( 方法是一个阻塞方法(经过一番混乱,我找到了一个可行的解决方案,但这对我来说似乎很奇怪,就像我在做一些潜在的"危险"事情一样。 我做的第一件事是创建一个新的 Runnable 和 Thread 对象:

//  "reader" is of type "BufferedReader"             
Runnable receiveResponse = new Runnable() {
boolean stop = false;
@Override
public void run() {
try {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
stop = true;
}
}, 5000);
char receive;
StringBuilder responseBuilder = new StringBuilder();
while (!stop && ((receive = (char) reader.read()) != END_OF_STREAM_CHAR)) {
responseBuilder.append(receive);
}
// If the server responds in time I can continue processing the response etc.
} catch (Exception ex) {
// Handle exception ...
}
}
};
Thread thread = new Thread(receiveResponse);
thread.start();

如您所见,我在 while 循环中使用了一个布尔"stop"(我在 5 秒后设置为 true(作为附加条件。 "reader.read(("方法是一个阻塞方法,所以如果我不实现某种类型的停止线程,如果服务器没有响应,这种方法将阻塞无限长的时间。这就是为什么我尝试使用计时器来简单地将"停止"布尔值设置为 true。

我知道这不是最好的解决方案,在某些时候我会完全重新设计整个事情,但我仍然想知道我现在正在做的事情是否正常。它当然有效,但可悲的是,这没有任何意义。

你是对的,这种再启动一个线程的方法并不完美。很难支持这样的代码。

我建议改用线程执行器。您的代码可能如下所示:

Runnable receiveResponse = new Runnable() {
...
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(receiveResponse);
try {
Object result = future.get(5000, TimeUnit.MILLISECONDS);
System.out.println("Completed successfully");
} catch (InterruptedException e) {
...
} catch (ExecutionException e) {
...
} catch (TimeoutException e) {
System.out.println("Timed out. Cancelling the runnable...");
future.cancel(true);
}
executor.shutdown();

最新更新