Остановка потока - PullRequest
5 голосов
/ 19 июня 2009

В приложении Java, когда пользователь нажимает кнопку загрузки, установление удаленного соединения и загрузка контента с удаленного устройства выполняется в отдельном потоке, и на экране появляется диалоговое окно, чтобы показать ход загрузки. Теперь в диалоговое окно добавлена ​​команда отмены, чтобы предоставить пользователю возможность отменить загрузку. Когда пользователь нажимает кнопку отмены, диалог может быть удален с помощью метода dispose () из программы, но как я могу остановить / убить поток, который уже был инициирован? Поток выполняет следующую задачу: 1. Устанавливает соединение с удаленным 2. Загружает контент с удаленного 3. Сохраняет контент локально (контент передается с помощью потоковой передачи) Пожалуйста, помогите мне решить эту проблему

Ответы [ 4 ]

6 голосов
/ 19 июня 2009

Остановка потока, вероятно, неправильный взгляд. Фактический ресурс, потребляемый одним потоком на настольном компьютере, не имеет значения. Думайте об этом как об отмене загрузки.

Если чтение блокируется, то это не является большой проблемой. Вы можете подождать, пока появятся какие-то данные, прежде чем больше не читать. Более резким подходом было бы вызвать close в потоке (из другого потока).

4 голосов
/ 19 июня 2009

Вам нужно проверить флаг остановки где-нибудь в вашей процедуре загрузки.

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 () .

3 голосов
/ 19 июня 2009

Во-первых, операция stop () на java.util.Thread устарела, и ее использование категорически не рекомендуется, так как она может оставлять вещи в нестабильном состоянии. Крайне желательно, чтобы вы отправляли сообщение в Runnable потока с просьбой остановить его безопасно.

Проблема, с которой вы столкнулись, заключается в том, что ваш поток блокирует операции ввода-вывода, и поэтому он не получит ваше сообщение до завершения ввода-вывода.

Лучшее, на что вы можете надеяться, если кто-то другой не придумал лучшего варианта, - это прерывать () поток и надеяться, что классы ввода-вывода заметят и остановят загрузку.

Edit: Javadoc для Thread.interrupt () действительно говорит, что ввод / вывод может быть прерван, если вы используете java.nio, но это маловероятно, что вы. «Нормальный» трафик java.io блокируется и не может быть прерван.

Почему не поддерживаются Thread.stop, Thread.suspend и Thread.resume?

1 голос
/ 19 июня 2009

Я предлагаю вам сделать то, что предложил Bombe (с изменяемой переменной), и просто оставить поток, чтобы умереть в фоновом режиме, возвращая управление обратно пользователю. Это может потратить немного времени на выборку последнего блока, но если пользователь может продолжать делать что-то еще, это не имеет большого значения. Если размеры вашего блока были относительно небольшими, потраченная пропускная способность не будет слишком большой, и время ввода-вывода в конечном итоге истечет и оно вернется, если соединение разорвалось.


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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...