在java应用程序中,当用户点击下载时,建立远程连接并从远程下载内容是在一个单独的线程中完成的,并在屏幕上弹出一个对话框以显示下载进度。现在,在对话框中添加了取消命令,以便为用户提供取消下载的选项。当用户点击取消按钮时,可以使用程序中的dispose()方法处理对话框,但是如何停止/终止已经启动的线程?线程执行以下任务:1。建立与远程的连接2.从远程下载内容3.在本地存储内容(内容通过流传输) 请帮我解决这个问题
答案 0 :(得分:6)
停止一个线程可能是错误的看待方式。桌面计算机上单个线程消耗的实际资源无关紧要。将其视为中止下载。
如果读取阻塞,那么这不是一个很大的问题。您可以等到有一些数据再不再读。一种更突然的方法是在流上调用close
(来自另一个线程)。
答案 1 :(得分:4)
您需要在下载例程中的某处检查停止标记。
public DownloadThread implements Runnable {
private boolean stop;
public void stop() { stop = true; }
public void run() {
while (!stop) {
// download a block, save it somewhere
}
}
}
当然这缺乏必要的同步,但这是关于如何在不使用已弃用的Thread.stop()的情况下停止线程。
答案 2 :(得分:3)
首先,不推荐使用java.util.Thread上的stop()操作,强烈建议不要使用它,因为它可能会使事物处于不稳定状态。你最好向Thread的Runnable发送一条消息,要求它安全地自行停止。
您遇到的问题是您的线程正在执行阻塞I / O操作,因此在I / O完成之前它不会收到您的消息。
除非其他人提出更好的选择,否则你可以期待的最好的方法是中断()线程,并希望I / O类注意并停止下载。
编辑:Thread.interrupt()的javadoc确实说如果你使用java.nio就可以中断I / IO,但是你不太可能。 “正常”java.io流量阻塞,无法中断。
Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?
答案 3 :(得分:1)
我建议你做Bombe建议的(使用volatile变量)并让线程在后台死掉,然后将控制权交还给用户。它可能花费一些时间来获取最后一个块,但如果用户可以继续做其他事情则无关紧要。如果您的块大小相对较小,浪费的带宽将不会太多,IO内容最终会超时并在连接变坏时返回。
public class Downloader {
protected final AtomicBoolean run = new AtomicBoolean(false);
protected final byte[] file;
protected volatile double progress = 0.0;
public download(URL url) {
run.set(true);
new Thread() {
@Override
public run() {
final ByteBuffer buffer = new ByteBuffer();
while(run) {
/* download chunk, e.g add to buffer, or whatever */
buffer.put(chunk);
progress = buffer.size().size() / fileTotalSize; //e.g
}
syncrhonized(Downloader.this) {
file = buffer.array();
}
}
}.start();
}
public void abort() {
run.set(false);
}
public double getProgress() {
return progress;
}
public synchronized byte[] getFile() {
return file;
}
}