| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > Как остановить Thread? |
| Автор: Aehn 13.5.2008, 14:27 | ||
| Есть класс myThread - наследник Thread Запускаю его нормально, а вот чтобы остановить вызываю myClass.stop() на что компилятор ругается
Но, помнится, когда-то давно этот пример нормально шел. Так как его надежно остановить? Добавлено через 4 минуты и 54 секунды Все, вопрос решился. Есть метод interrupt() |
| Автор: $tatic 13.5.2008, 14:59 | ||||
| Aehn, вообще-то это неправильно, документация предлагает сделать вот так: было
стало
|
| Автор: Дрон 26.5.2008, 09:44 |
| Подниму тему. Что-то я так и не понял, как нормально прервать поток, раз stop() теперь deprecated? У меня есть поток, который в фоновом режиме загружает из JPEG большую картинку (например 80 мегапикселей). Такая картинка занимает порядка 500 мегабайт в памяти и загружается около 7 секунд. Если вдруг на середине загрузки я узнал, что мне эта картинка не нужна, а нужна другая, то как мне прервать поток? Метод interrupt() не подходит, так как он не прерывает поток, а только выставляет соответствующий статус потока, который я не могу проверить пока картинка полностью не загрузится. А если вторая картинка тоже на 500 мегабайт, то обе сразу в память могут и не поместиться. Что делать? |
| Автор: Hidrag 26.5.2008, 10:06 |
| Намудрили то Как вариант: 1. Создаем класс, наследуем его от Thread. 2. В этом классе создаем паблик переменную логического типа. 3. В методе run этого класса определяем место или места где смотрим эту переменную и если она истина (или ложь, смотря как спрограммировать) то делаем break или return опять же в зависимости от того что делается в этом методе. 4. В классе откуда будет запускаться поток создаем объект выше созданного класса. 5. Вызываем у него метод start() - все поток запущен! 6. Если нужно "убить поток" у созданного объекта потока меняем логическую переменную, в потоке эта переменная проверится там где мы ее ранее определили и поток остановится. Что то вроде такого, все просто! Особенно удобно если в потоке крутится какой то цикл. |
| Автор: Platon 26.5.2008, 10:35 |
| Hidrag, между прочим, Дрон не намудрил, он работает с interrupt, и на мой взгляд это куда правильней, чем плодить доп. логические переменные. Случай, конечно, интересный. Я так же задавался вопросом, как можно без всяких проверок рубануть поток? Таким образом нам нужно писать потокозависимые компоненты, т.е. к примеру загрузчик изображения из сети, который каждые N байтов проверяет, актуальна ли еще его загрузка. |
| Автор: Дрон 26.5.2008, 12:03 | ||
Меня интересует мой конкретный случай. Общие подходы я отлично знаю, но вот в моём случае они не работают. В моём потоке и цикла никакого нет, упрощённо говоря он вообще состоит из вызова одного единственного метода из ImageIO, загружающего картинку.
О том и речь :( Я предполагаю, что можно грузить картинку по частям (tiles), разбив её на прямоугольники размером в пару-тройку мегапикселей и потом собирать в одну большую... Но мне кажется, что помимо усложнения кода, это потребует дополнительного времени на обработку и увеличит расход памяти, так что в данном случае проще вызвать Thread.stop(). Ведь то, что он deprecated не означает, что он не работает? Или есть шанс, что потом они его вообще выкинут? |
| Автор: Platon 26.5.2008, 12:19 |
Именно, хотя уже какую версию этот stop тянется. |
| Автор: Дрон 26.5.2008, 12:43 |
Эх... Хотя думаю, что всё равно не выкинут Но мне, скорее всего, придётся всё-таки по кускам картинку грузить, благо все соответствующие методы для этого есть. Главное, чтобы на быстродействие и память это не сильно влияло. |
| Автор: Maksym 26.5.2008, 17:07 |
| Дрон Думаю, нужно грузить картинку не метдами ImageIO, а каким-нибудь простым байтовым стримом, где ты в цикле выбирашь данные в буфер. Там есть возможность сделать любую проверку на каждой итерации и прерваться при необходимости. А потом, после окончания загрузки, целиком загруженные данные можно отдать в более высокоуровневые методы из ImageIO. |
| Автор: Дрон 26.5.2008, 17:15 | ||
Там JPEG. Сам файл занимает, скажем, порядка 20-30 мегабайт и загрузить его в память -- один миг, проблема состоит в декодировании JPEG, которое и занимает основное время. Писать собственный декодер я пока не готов -- и так времени нет Я уже различными хитростям смог оптимизировать остальные операции с картинками, осталось только забороть загрузку. |
| Автор: math64 27.5.2008, 13:17 | ||
|
| Автор: Дрон 27.5.2008, 13:47 |
| math64, это вроде не совсем то. Но в общем случае -- да, можно было использовать перегруженный InputStream, при условии что декодирование идёт вместе с чтением. А вот если сначала читается весь файл, а только потом декодируется, то этот способ не пойдёт -- как внутри устроен ImageIO я не знаю. Свою проблему я решил даже проще -- как оказалось ImageReader из ImageIO умеет сообщать свой прогресс, и вот в обрабочик прогресса я и добавил проверку на то не был ли прерван поток. Так что с потоками пока разобрался. Всем отвечавшим спасибо |
| Автор: COVD 27.5.2008, 17:04 | ||
interrupt по моему представлению, прерывает не выполнение потока, а ожидание. Если поток стоит в wait(), то interrupt() его разбудит. Если же поток выполняет последовательность команд, например, вычисления в цикле, то interrupt() никакого эффекта не даст - у потока нет никакого внутреннего флага, который он бы проверял на каждом шагу. Это дело программиста - "плодить доп. логические переменные", если надо. И это компетенция программиста ставить проверку флага в правильном месте: например, поток открыл соединение, потом проверил флаг, и обнаружил команду "умереть". Так перед смертью он должен открытое соединение закрыть. Освободить захваченные ресурсы. |
| Автор: Дрон 27.5.2008, 18:02 | ||
Использование interrupt() избавляет от необходимости вводить дополнительную булевую переменную, потому что у потока есть метод isInterrupted() позволяющий проверить, требуется ли прервать выполнение. |
| Автор: mindflyer 28.5.2008, 11:47 | ||
Иногда лучше всё же добавлять свою переменную. Уже писал где-то на форуме - столкнулся с ситуацией, когда interrupt перехватывался в сторонней библиотеке, обрабатывался и сбрасывался флаг. В итоге, если interrupt был вызван, когда управление было не в моём коде, а в коде той библиотеки, то мой код вызывая inInterrupted() получал false и продолжал выполнение. |
| Автор: Дрон 28.5.2008, 12:27 | ||
Хм. А вот это действительно возможно. |
| Автор: COVD 28.5.2008, 15:49 | ||||
Спасибо, совсем забыл.
Это просто вредительство |
| Автор: AlexeyVorotnikov 28.5.2008, 16:39 | ||||||||
У потока так же есть метод public static boolean interrupted() в описании которого сказано:
|
| Автор: COVD 28.5.2008, 17:14 |
| Спасибо. |