我有一个连接到网址的线程来获取一些数据。
有时方法httpConnection.connect();
得到的响应时间过长,我想将此连接线程的加载对话框限制为5 seg。
我尝试在代码中添加超时,但它不起作用 !!
URL formattedUrl = new URL(url);
URLConnection connection = formattedUrl.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setAllowUserInteraction(false);
httpConnection.setInstanceFollowRedirects(true);
httpConnection.setRequestMethod("GET");
httpConnection.setConnectTimeout(5000);
httpConnection.setReadTimeout(5000);
httpConnection.connect();
所以,我必须在5000秒过后或者当用户按下手机上的后退键时停止连接方法和线程。
如何实现这一目标?我找不到关于在android中使用url连接线程做这项工作的信息。
感谢
答案 0 :(得分:3)
URLConnection上的超时设置不足以提供所需的超时控制。原因是:
setConnectTimeout()设置仅与服务器建立连接的超时。因此,只有在打开连接时才会触发超时,无法在规定的时间内建立连接。
setReadTimeount()设置读取可用数据的超时。为此,仅当任何单个读取操作阻止的时间超过设定的时间量时,才会触发超时。因此,即使在连接速度很慢的情况下,每次读取操作都不会接近超时阈值,但读取所有数据的总时间相当长。
将超时应用于整个读取工作单元的一种解决方案是使用Java 5及更高版本中的并发功能。特别是,使用ExecutorService和Future就足够了。
Runnable task = new Runnable() {
public void run() {
// original code to read data from a URL
}
};
ExecutorService executor = Executors.newSingleThreadExecutor(); // or any other implementation
Future<?> future = executor.submit(task);
try {
future.get(5, TimeUnit.SECONDS); // wait 5 seconds for task to complete
// success
} catch (TimeoutException ex) {
// handle timeout
} finally {
executor.shutdownNow(); // cleanup
}
答案 1 :(得分:3)
Brent Worden的回答是正确的。但他的解决方案存在问题。如果任务超时启动,则调用future.get
的线程将按预期获得异常。但是,执行Runnable.run()
方法的工作线程可能仍然卡在等待连接或读取完成。
解决这个问题很困难。据我所知,解除正在等待套接字连接或套接字流读取或写入的线程的唯一可靠方法是在close()
对象上调用Socket
。使用该方法(此处)的问题是标准HttpUrlConnection
对象不公开Socket
对象。
我的建议是使用Apache Http客户端库。此问题解释了如何使用HttpClient中止请求:Cancel an HttpClient request
答案 2 :(得分:0)
您只需要调用URLConnection.setConnectTimeout(millis)即可实现您的要求。如果指定的超时到期,则抛出SocketTimeoutException。
try {
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
con.setConnectTimeout(5000); //set timeout to 5 seconds
} catch (java.net.SocketTimeoutException e) {
//DO SOMETHING
} catch (java.io.IOException e) {
//DO SOMETHING
}
值得注意的是,它说明了以下内容:
这种方法的一些非标准实施可能会忽略 指定超时。要查看连接超时设置,请致电 getConnectTimeout()。