Как установить тайм-аут для BufferedReader на основе URLConnection в Java?
Вопрос
Я хочу прочитать содержимое URL-адреса, но не хочу «зависать», если URL-адрес не отвечает.Я создал BufferedReader, используя URL-адрес...
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.4:
Я предполагаю, что тайм-аут соединения (URLConnection.setConnectTimeout(int timeout)
) бесполезно, потому что вы ведете какую-то потоковую передачу.
---Не убивайте ветку--- Это может вызвать неизвестные проблемы, открытые дескрипторы и т. д.
Создайте java.util.TimerTask, где вы проверите, завершили ли вы процесс, в противном случае закройте BufferedReader и OutputStream URLConnection.
Вставьте логический флаг isFinished
и установите для него значение true в конце цикла и значение false перед циклом
TimerTask ft = new TimerTask(){
public void run(){
if (!isFinished){
urlConn.getInputStream().close();
urlConn.getOutputStream().close();
}
}
};
(new Timer()).schedule(ft, timeout);
Вероятно, это вызовет исключение io, поэтому вам придется его перехватить.Исключение само по себе не является чем-то плохим.Я опускаю некоторые объявления (т.е.Finals), чтобы анонимный класс мог получить доступ к вашим переменным.Если нет, создайте POJO, который поддерживает ссылку, и передайте его в задачу таймера.
Начиная с Java 1.5, можно установить тайм-аут чтения в миллисекундах для базового сокета с помощью метода setReadTimeout(int timeout) в классе URLConnection.
Обратите внимание, что существует также параметр «setConnectTimeout(int timeout)», который будет делать то же самое для первоначального подключения к удаленному серверу, поэтому важно также установить его.
Совсем недавно я работал над этой проблемой в среде JVM 1.4.Стандартный ответ — использовать системные свойства sun.net.client.defaultReadTimeout (время ожидания чтения) и/или sun.net.client.defaultConnectTimeout.Они задокументированы на Сетевые свойства и может быть установлен с помощью аргумента -D в командной строке Java или с помощью вызова метода System.setProperty.
Предположительно, они кэшируются реализацией, поэтому вы не можете изменить их с одного на другое, поэтому, если они используются один раз, значения сохраняются.
Кроме того, они не работают для SSL-соединений, например HttpsURLConnection.Есть и другие способы справиться с этим, используя специальный SSLSocketFactory.
Опять же, все это относится к JVM 1.4.x.В версии 1.5 и выше вам доступно больше методов в API (как отмечали другие респонденты выше).
Для Java 1.4 вы можете использовать SimpleHttpConnectionManager.getConnectionWithTimeout(hostConf,CONNECTION_TIMEOUT) из Apache.