Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 停止线程_Java_Multithreading_Io - Fatal编程技术网

Java 停止线程

Java 停止线程,java,multithreading,io,Java,Multithreading,Io,在java应用程序中,当用户点击下载时,在单独的线程中建立远程连接并从远程下载内容,屏幕上会弹出一个对话框来显示下载进度。现在,对话框中添加了一个cancel命令,以便为用户提供取消下载的选项。当用户点击取消按钮时,可以使用程序中的dispose()方法释放对话框,但是如何停止/终止已经启动的线程?线程执行以下任务:1.与远程服务器建立连接2.从远程服务器下载内容3.在本地存储内容(通过流媒体传输内容) 请帮助我解决此问题您需要在下载例程中的某个位置检查停止标志 public DownloadT

在java应用程序中,当用户点击下载时,在单独的线程中建立远程连接并从远程下载内容,屏幕上会弹出一个对话框来显示下载进度。现在,对话框中添加了一个cancel命令,以便为用户提供取消下载的选项。当用户点击取消按钮时,可以使用程序中的dispose()方法释放对话框,但是如何停止/终止已经启动的线程?线程执行以下任务:1.与远程服务器建立连接2.从远程服务器下载内容3.在本地存储内容(通过流媒体传输内容)
请帮助我解决此问题

您需要在下载例程中的某个位置检查停止标志

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!