In [259]: get_in_chunks = lambda itr,n: ( (v for _,v in g) for _,g in itertools.groupby(enumerate(itr),lambda (ind,_): ind/n)) In [260]: list(list(x) for x in get_in_chunks(range(30),7)) Out[260]: [[0, 1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13], [14, 15, 16, 17, 18, 19, 20], [21, 22, 23, 24, 25, 26, 27], [28, 29]]
Stopping a thread is probably the wrong way to look at. The actual resource consumed by a single thread on a desktop machine is irrelevant. Think of it as aborting the download.
If the read is blocking, then that isn't really much of a problem. You can wait until there is some data before not reading again. A more abrupt approach would be to call close
on the stream (from another thread).
Вам нужно проверить наличие флага остановки где-нибудь в вашей процедуре загрузки.
public DownloadThread implements Runnable {
private boolean stop;
public void stop() { stop = true; }
public void run() {
while (!stop) {
// download a block, save it somewhere
}
}
}
Конечно, здесь отсутствует необходимая синхронизация, но речь идет о том, как остановить поток без использования устаревшего потока .stop () .
Я предлагаю вам сделать то, что предложил Бомб (с изменчивой переменной), и просто оставить поток умирать в фоновом режиме, возвращая управление обратно пользователю. Он может потратить немного времени на выборку последнего блока, но если пользователь может продолжать делать что-то еще, это не имеет большого значения. Если размеры ваших блоков были относительно небольшими, пропускная способность не будет слишком большой, и данные ввода-вывода в конечном итоге будут отключены и вернутся, если соединение ухудшилось.
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;
}
}
Во-первых, операция stop () для java.util. Thread устарел, и его использование настоятельно не рекомендуется, так как оно может оставить вещи в нестабильном состоянии. Гораздо предпочтительнее, чтобы вы отправляли сообщение Runnable потока с просьбой о его безопасном останове.
Проблема в том, что ваш поток выполняет блокирующие операции ввода-вывода, и поэтому он не получит ваше сообщение до тех пор, пока I / O завершен.
Лучшее, на что вы можете надеяться, если кто-то другой не предложит лучший вариант, - это interrupt () Thread и надеяться, что классы ввода-вывода заметят и остановят загрузку.
Изменить: javadoc для Thread.interrupt () действительно говорит, что ввод / вывод может быть прерван, если вы используете java.nio, но это очень маловероятно. «Нормальный» трафик java.io блокируется и не может быть прерван.
Почему Thread.stop, Thread.suspend и Thread. возобновить Устарело?