停止一个线程

时间:2009-06-19 10:11:01

标签: java multithreading io

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

4 个答案:

答案 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;
    }
}