Java 停止线程
在java应用程序中,当用户点击下载时,在单独的线程中建立远程连接并从远程下载内容,屏幕上会弹出一个对话框来显示下载进度。现在,对话框中添加了一个cancel命令,以便为用户提供取消下载的选项。当用户点击取消按钮时,可以使用程序中的dispose()方法释放对话框,但是如何停止/终止已经启动的线程?线程执行以下任务:1.与远程服务器建立连接2.从远程服务器下载内容3.在本地存储内容(通过流媒体传输内容)Java 停止线程,java,multithreading,io,Java,Multithreading,Io,在java应用程序中,当用户点击下载时,在单独的线程中建立远程连接并从远程下载内容,屏幕上会弹出一个对话框来显示下载进度。现在,对话框中添加了一个cancel命令,以便为用户提供取消下载的选项。当用户点击取消按钮时,可以使用程序中的dispose()方法释放对话框,但是如何停止/终止已经启动的线程?线程执行以下任务:1.与远程服务器建立连接2.从远程服务器下载内容3.在本地存储内容(通过流媒体传输内容) 请帮助我解决此问题您需要在下载例程中的某个位置检查停止标志 public DownloadT
请帮助我解决此问题您需要在下载例程中的某个位置检查停止标志
public DownloadThread implements Runnable {
private boolean stop;
public void stop() { stop = true; }
public void run() {
while (!stop) {
// download a block, save it somewhere
}
}
}
当然,这缺少必要的同步,但这是关于如何停止线程而不使用已弃用的。首先,java.util.thread上的stop()操作已弃用,强烈建议不要使用,因为它会使事情处于不稳定状态。最好是向线程的Runnable发送一条消息,要求它安全地停止自身
您的问题是,您的线程正在执行阻塞I/O操作,因此在I/O完成之前,它不会接收您的消息
除非有人提出更好的选择,否则您最好能中断()线程,并希望I/O类注意到并停止下载
Edit:Thread.interrupt()的javadoc确实指出,如果使用java.nio,I/IO可以被中断,但不太可能被中断。“正常”java.io通信阻塞,无法中断
停止线程可能是错误的看待方法。桌面计算机上单个线程消耗的实际资源是无关的。可以将其视为中止下载
如果读取被阻塞,那么这并不是什么大问题。您可以等到有一些数据后再不读取。一种更突然的方法是(从另一个线程)调用流上的
close
。我建议您按照Bombe的建议(使用一个可变变量)执行操作,让线程在后台死掉,将控制权返回给用户。它可能会花费一点时间来获取最后一个块,但如果用户可以继续做其他事情,那也没什么大不了的。如果您的块大小相对较小,浪费的带宽不会太多,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;
}
}
IIRC,可中断IO仅在Solaris上默认启用。打断通常是邪恶的。@Tom-你能详细说明一下“打断通常是邪恶的”吗?e.vil(形容词):以不幸或痛苦为特征或伴随着不幸或痛苦;不幸的;灾难您不知道您正在中断什么(可能是类加载或一些实现细节),中断通常没有正确处理,中断的含义在本地上下文中通常不清楚。OP说他正在使用流式I/O,因此他们可能正在使用while循环来下拉和存储数据。他们可以在该循环内执行停止检查。但是,如果他们在一个卡盘里抓住了所有的东西,那么他们就被塞住了。正如“jgubby”所指出的,上面的停止变量应该是易变的。@Fredrik我不同意这种说法。见我对jgubby回答的评论。我不同意让变量波动。这将影响每个循环中的性能。如果你保持变量非易失性,你将得到的唯一惩罚是线程停止时的轻微延迟(你甚至无法测量)。我不同意这种说法。与网络操作的延迟相比,易失性变量的设置很小,而依赖于线程之间数据最终传播的程序实际上是不正确的。不要为了速度而优化同步!设置一个可变变量确实不是问题。但是访问易失性变量意味着它不在线程缓存中,从而影响性能。我同意不应该过早地进行优化,但如果这个循环很重要,应该考虑这个问题。从远程下载内容不是在迭代过程中完成的。代码在移动应用程序中执行,当用户选择下载内容时,内容通过GPRS下载。JavaME没有nio。因此,我提供了伪代码。新线程(new Runnable(){try{//open http connection to remote server//display dialog with progress indicator and cancel命令//从远程连接获取输入流//逐字节读取流(update progress indicator)//通过输出流存储内容}catch(IOException ioe){});当用户单击“取消”命令时,我如何中止此线程?也请检查这些问题1)2)应该注意,根据以下原始作者的评论之一,这是针对Java ME的,而不是针对标准桌面Java!