Отменить загрузку файла из другого потока в любое время
Я использую HttpURLConnection для загрузки файла. Можно ли отменить загрузку из другого потока? Если нет, какой метод загрузки файлов я должен использовать?
Ответы
Ответ 1
Мое предложение было бы использовать HttpClient вместо HttpUrlConnection. Это лучшая библиотека во многих отношениях.
Затем вы можете использовать:
final SimpleHttpConnectionManager connectionManager =
new SimpleHttpConnectionManager();
final HttpClient client = new HttpClient(connectionManager);
// ... and when it time to close the connection from another thread
connectionManager.shutdown();
Если вам нужно закрыть несколько подключений по нескольким потокам, вы можете повторно использовать один экземпляр HttpClient и закрыть их все за один проход следующим образом:
static MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
// HttpClient instance that can be shared across threads and create multiple connections
static HttpClient client = new HttpClient(connectionManager);
// ... and when it time to close connections
connectionManager.shutdown();
Ответ 2
Вы можете использовать InterruptedException в сочетании с задачами/исполнителями. Ваш порожденный поток должен улавливать InterruptedException, обертывая try/catch по методу HttpURLConnection, который выполняет загрузку. Java Concurrency На практике, главы 6 и 7 имеют значение. В частности, 7.2 "Остановка службы на основе потоков".
Ответ 3
Мне удалось получить close()
в InputStream, чтобы вернуть read()
.
Я понимаю, что этот код ужасен. Он эффективно запускает сервер, который прослушивает порт 32323 для HTTP-соединения. Затем он будет считывать все доступные ему данные и записывать фиктивные данные до тех пор, пока клиент не сможет получить InputStream. Как только клиент сможет получить входной поток, сервер перестает записывать данные, имитирующие сломанную загрузку.
Это такой тривиальный пример, что он может не работать в вашем реальном мире.
Затем клиент закрывает поток с помощью InputStream.close()
, из-за чего InputStream.read()
бросается.
public class Main {
public static void main(String[] args) throws Exception {
final Object lock = new Object();
final boolean test[] = new boolean[1];
Thread thread = new Thread(new Runnable() {
public void run() {
try {
ServerSocket server = new ServerSocket(32323);
Socket socket = server.accept();
System.out.println("New client");
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
while (true) {
is.read();
///System.out.println(is.read());
if (!test[0]) {
os.write(0);
} else {
synchronized (lock) {
lock.notifyAll();
}
}
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
});
thread.start();
final InputStream[] asyncStream = new InputStream[1];
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://localhost:32323");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream is = connection.getInputStream();
System.out.println("got input stream");
asyncStream[0] = is;
test[0] = true;
while (true) {
System.out.print("read start");
is.read();
System.out.println(" done");
}
} catch (IOException ex) {
throw new RuntimeException("Read failed",ex);
}
}
});
thread2.start();
// wait enough time for data to run out
synchronized (lock) {
lock.wait();
}
System.out.println("Closing connection");
asyncStream[0].close();
System.out.println("Connection closed");
}
Выход
New client
got input stream
read start done
read start done
read start done
read start done
read start done
read start done
read startClosing connection
done
read startRead failed
Connection closed
Ответ 4
Вы пытались асинхронно закрывать соединение InputStream из другого потока? Не уверен, правильно ли он, но он работает с сокетами, поэтому, если Java использует аналогичный проект, здесь он тоже может работать. Но даже если это работает, лучше искать подтверждение из какого-то надежного источника, хотя, похоже, он работает, но иногда не работает, как это часто бывает при многопоточном программировании.
ИЗМЕНИТЬ
По-видимому, он не работает.
Ответ 5
Вы можете прочитать блок данных куском (обычно это нужно сделать) и проверить флаг boolean, который установлен в true
(указывает на остановку) из другого потока (рассмотрите возможность использования volatile
). Здесь проблема может заключаться в том, что чтение фрагмента занимает слишком много времени, и он будет ожидать считывания фрагмента перед проверкой флага. Я не уверен, что закрытие соединения из другого потока - хорошая идея (хотя нет источников информации). Но если вы это сделаете, вы можете использовать флаг, чтобы отличать реальные сбои подключения от остановки.
Ответ 6
Я предполагаю, что у вас нет доступа к входному потоку, иначе вы могли бы просто закрыть его
Если не самое лучшее, что нужно сделать, просто установите приоритет потока на 0
Это минимизирует количество срезов времени, выделенных этому потоку.
Ответ 7
InputStream.close()
может не работать, но вы попробовали HttpURLConnection.disconnect()
? Если я не ошибаюсь, он должен принудительно отключиться, и поэтому InputStream.read()
должен возвращать -1. Вы должны быть уверены, чтобы снова подключиться, прежде чем продолжить.