7

我有一个线程连接到一个 url 以获取一些数据。

有时该方法httpConnection.connect();花费了太多时间来获得响应,我想将此连接线程的加载对话框限制为 5 段。

我尝试在代码中添加超时,但它不起作用

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 秒过去或当用户按下手机上的返回键时停止连接方法和线程。

如何做到这一点?我找不到有关在带有 url 连接线程的 android 中执行此工作的信息。

谢谢

4

3 回答 3

3

Brent Worden 的答案是正确的。但是他的解决方案有问题。如果任务超时启动,调用的线程future.get将按预期获得异常。但是,正在执行该Runnable.run()方法的工作线程可能仍会卡在等待连接或读取完成。

解决这个问题很困难。据我所知,解除正在等待套接字连接或套接字流读取或写入的线程的唯一可靠方法是调用close()Socket对象。使用这种方法(这里)的问题是标准HttpUrlConnection对象没有暴露Socket对象。

我的建议是使用 Apache Http 客户端库。这个问题解释了如何在使用 HttpClient 时中止请求:取消 HttpClient 请求

于 2012-10-06T03:25:30.473 回答
3

URLConnection 上的超时设置不足以提供所需的超时控制。原因是:

  • setConnectTimeout() 设置与服务器建立连接的超时时间。因此,只有在打开连接时,无法在规定的时间内建立连接时才会触发超时。

  • setReadTimeout() 设置读取可用数据的超时时间。为此,只有在任何单个读取操作阻塞超过设置的时间量时才会触发超时。因此,即使在慢速连接上,每个读取操作也很有可能永远不会接近超时阈值,但是读取所有数据的总时间相当长。

将超时应用于整个读取工作单元的一种解决方案是使用 Java 5 及更高版本中的并发功能。特别是,使用ExecutorServiceFuture就足够了。

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
}
于 2012-10-06T01:41:10.950 回答
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()。

于 2012-10-05T23:42:32.363 回答