如何基于Java中的URLConnection对BufferedReader设置超时?
我想读取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中使用更多方法(如上述其他响应者所述)。