如何基于Java中的URLConnection对BufferedReader设置超时?

时间:2020-03-06 14:21:47  来源:igfitidea点击:

我想读取URL的内容,但如果URL没有响应,则不想"挂起"。我已经使用URL创建了BufferedReader ...

URL theURL = new URL(url);
URLConnection urlConn = theURL.openConnection();
urlConn.setDoOutput(true);
BufferedReader urlReader = new BufferedReader(newInputStreamReader(urlConn.getInputStream()));

...然后开始循环以读取内容...

do
    {
    buf = urlReader.readLine();
    if (buf != null)
        {
        resultBuffer.append(buf);
        resultBuffer.append("\n");
        }
    }
while (buf != null);

...但是,如果读取挂起,则应用程序挂起。

有没有一种方法,无需将代码精简到套接字级别,就可以在必要时使读取"超时"?

解决方案

我认为URLConnection.setReadTimeout是我们想要的。

从Java 1.5开始,可以通过URLConnection类上的" setReadTimeout(int timeout)"方法在基础套接字上设置读取超时(以毫秒为单位)。

请注意,还有一个" setConnectTimeout(int timeout)",它将对与远程服务器的初始连接执行相同的操作,因此也必须进行设置。

如果我们有Java 1.4:

我认为连接超时(URLConnection.setConnectTimeout(int timeout))没有用,因为我们正在执行某种流传输。

---请勿杀死线程-这可能会导致未知问题,打开描述符等。

生成一个java.util.TimerTask,我们将在其中检查是否已完成该过程,否则,请关闭BufferedReader和URLConnection的OutputStream

插入一个布尔值标志" isFinished",并在循环结束时将其设置为true,在循环之前将其设置为false

TimerTask ft = new TimerTask(){
   public void run(){
     if (!isFinished){
       urlConn.getInputStream().close();
      urlConn.getOutputStream().close();
     }
   }
};

(new Timer()).schedule(ft, timeout);

这可能会导致ioexception,因此我们必须抓住它。异常本身并不是一件坏事。
我省略了一些声明(即Finals),以便匿名类可以访问变量。如果不是,则创建一个维护引用的POJO并将其传递给timertask

我最近在JVM 1.4环境中一直在研究此问题。常见的答案是使用系统属性sun.net.client.defaultReadTimeout(读取超时)和/或者sun.net.client.defaultConnectTimeout。这些在"网络属性"中有说明,可以通过Java命令行上的-D参数或者通过System.setProperty方法调用进行设置。

假定这些已由实现缓存,所以我们不能将它们从一件事更改为另一件事,因此将它们一次使用一次,将保留这些值。

此外,它们实际上不适用于HttpsURLConnection的SSL连接。还有其他方法可以使用自定义SSLSocketFactory处理该问题。

同样,所有这些都适用于JVM1.4.x。在1.5及更高版本中,我们可以在API中使用更多方法(如上述其他响应者所述)。