随时从其他线程取消文件下载

时间:2010-12-14 17:57:48

标签: java

我正在使用HttpURLConnection下载文件。我可以从其他线程取消下载吗?如果没有,我应该使用哪种文件下载方法?

7 个答案:

答案 0 :(得分:6)

我的建议是使用HttpClient而不是HttpUrlConnection。它在很多方面都是一个更好的图书馆。

然后,您可以使用:

final SimpleHttpConnectionManager connectionManager = 
            new SimpleHttpConnectionManager();
final HttpClient client = new HttpClient(connectionManager);

// ... and when it's 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's time to close connections
connectionManager.shutdown();

答案 1 :(得分:3)

您可以将InterruptedException与Tasks / Executors结合使用。你的衍生线程应该能够通过在正在进行下载的HttpURLConnection方法周围包装try / catch来捕获InterruptedException。 Java Concurrency在实践中,第6章和第7章是相关的。特别是7.2“停止基于线程的服务”。

答案 2 :(得分:1)

我能够在InputStream上获得close()以返回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

答案 3 :(得分:0)

您是否尝试从另一个线程异步关闭连接的InputStream?不确定它是否正确,但它适用于套接字,所以如果Java在这里使用类似的设计模式,它也可以工作。但是,即使它有效,也可以从一些可靠的源代码中获得更好的确认,因为它似乎可以工作但有时失败,因为它经常发生在多线程编程中。

修改

显然,it doesn't work

答案 4 :(得分:0)

您可以按块读取数据块(通常应该这样做)并检查从另一个线程设置为true(表示停止)的布尔标志(考虑使用volatile)。这里的问题可能是如果读取块太长并且在检查标志之前它将等待读取块。我不确定从另一个线程关闭连接是个好主意(尽管没有信息来源)。但是如果你这样做,你可以使用一个标志来区分真正的连接故障和停止。

答案 5 :(得分:0)

我假设您无权访问输入流,否则您可以关闭它 如果不是,那么下一个要做的就是将线程优先级设置为0

这将最小化分配给该线程的时间片数。

答案 6 :(得分:0)

InputStream.close()可能不起作用,但您是否尝试HttpURLConnection.disconnect()?如果我没有错误,它应该强行断开连接,因此InputStream.read()应该返回-1。不过,您应该确保重新连接,然后继续。