Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как остановить Thread? jdk1.5.0_04 *.stop() has been deprecated 
V
    Опции темы
Aehn
Дата 13.5.2008, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 64
Регистрация: 24.4.2008

Репутация: нет
Всего: нет



Есть класс myThread - наследник Thread
Запускаю его нормально, а вот чтобы остановить вызываю
myClass.stop()
на что компилятор ругается
Код

    public void stop()
    {
        if(myThread != null)
        {
           myThread.stop();
           myThread = null;
        }
    }

Но, помнится, когда-то давно этот пример нормально шел.
Так как его надежно остановить?

Добавлено через 4 минуты и 54 секунды
Все, вопрос  решился. Есть метод interrupt()

Это сообщение отредактировал(а) Aehn - 13.5.2008, 14:27
PM MAIL   Вверх
$tatic
Дата 13.5.2008, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 28.1.2005

Репутация: нет
Всего: 22



Aehn,
вообще-то это неправильно, документация предлагает сделать вот так:

было
Код

    private Thread blinker;

    public void start() {
        blinker = new Thread(this);
        blinker.start();
    }

    public void stop() {
        blinker.stop();  // UNSAFE!
    }

    public void run() {
        Thread thisThread = Thread.currentThread();
        while (true) {
            try {
                thisThread.sleep(interval);
            } catch (InterruptedException e){
            }
            repaint();
        }
    }


стало
Код

    private volatile Thread blinker;

    public void stop() {
        blinker = null;
    }

    public void run() {
        Thread thisThread = Thread.currentThread();
        while (blinker == thisThread) {
            try {
                thisThread.sleep(interval);
            } catch (InterruptedException e){
            }
            repaint();
        }
    }

PM MAIL   Вверх
Дрон
Дата 26.5.2008, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Подниму тему. Что-то я так и не понял, как нормально прервать поток, раз stop() теперь deprecated?

У меня есть поток, который в фоновом режиме загружает из JPEG большую картинку (например 80 мегапикселей). Такая картинка занимает порядка 500 мегабайт в памяти и загружается около 7 секунд.

Если вдруг на середине загрузки я узнал, что мне эта картинка не нужна, а нужна другая, то как мне прервать поток?
Метод interrupt() не подходит, так как он не прерывает поток, а только выставляет соответствующий статус потока, который я не могу проверить пока картинка полностью не загрузится. А если вторая картинка тоже на 500 мегабайт, то обе сразу в память могут и не поместиться.

Что делать?


--------------------
Да. Именно так.
PM   Вверх
Hidrag
Дата 26.5.2008, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 877
Регистрация: 9.4.2005
Где: JDK

Репутация: 3
Всего: 25



Намудрили то smile Куда все проще!

Как вариант:
1. Создаем класс, наследуем его от Thread.
2. В этом классе создаем паблик переменную логического типа.
3. В методе run этого класса определяем место или места где смотрим эту переменную и если она истина (или ложь, смотря как спрограммировать) то делаем break или return опять же в зависимости от того что делается в этом методе.
4. В классе откуда будет запускаться поток создаем объект выше созданного класса.
5. Вызываем у него метод start() - все поток запущен!
6. Если нужно "убить поток" у созданного объекта потока меняем логическую переменную, в потоке эта переменная проверится там где мы ее ранее определили и поток остановится.

Что то вроде такого, все просто! Особенно удобно если в потоке крутится какой то цикл.



--------------------
user posted image
PM WWW ICQ   Вверх
Platon
Дата 26.5.2008, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



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

Случай, конечно, интересный. Я так же задавался вопросом, как можно без всяких проверок рубануть поток?
Таким образом нам нужно писать потокозависимые компоненты, т.е. к примеру загрузчик изображения из сети, который каждые N байтов проверяет, актуальна ли еще его загрузка.
PM MAIL ICQ   Вверх
Hidrag
Дата 26.5.2008, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 877
Регистрация: 9.4.2005
Где: JDK

Репутация: 3
Всего: 25



Цитата(Platon @  26.5.2008,  10:35 Найти цитируемый пост)
Таким образом нам нужно писать потокозависимые компоненты, т.е. к примеру загрузчик изображения из сети, который каждые N байтов проверяет, актуальна ли еще его загрузка. 


и


Цитата(Hidrag @  26.5.2008,  10:06 Найти цитируемый пост)
3. В методе run этого класса определяем место или места где смотрим эту переменную и если она истина (или ложь, смотря как спрограммировать) то делаем break или return опять же в зависимости от того что делается в этом методе.


Тоже самое и получается smile ты предлагаешь проверять актуальность, а я предложил в качестве актуальности булеву переменную smile а break, return или загрузка новой картинки зависит от задачи )


--------------------
user posted image
PM WWW ICQ   Вверх
Дрон
Дата 26.5.2008, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(Hidrag @  26.5.2008,  10:06 Найти цитируемый пост)
Особенно удобно если в потоке крутится какой то цикл.

Меня интересует мой конкретный случай. Общие подходы я отлично знаю, но вот в моём случае они не работают. В моём потоке и цикла никакого нет, упрощённо говоря он вообще состоит из вызова одного единственного метода из ImageIO, загружающего картинку.

Цитата(Platon @  26.5.2008,  10:35 Найти цитируемый пост)
Таким образом нам нужно писать потокозависимые компоненты, т.е. к примеру загрузчик изображения из сети, который каждые N байтов проверяет, актуальна ли еще его загрузка. 

О том и речь :(
Я предполагаю, что можно грузить картинку по частям (tiles), разбив её на прямоугольники размером в пару-тройку мегапикселей и потом собирать в одну большую... Но мне кажется, что помимо усложнения кода, это потребует дополнительного времени на обработку и увеличит расход памяти, так что в данном случае проще вызвать Thread.stop().

Ведь то, что он deprecated не означает, что он не работает? Или есть шанс, что потом они его вообще выкинут?


Это сообщение отредактировал(а) Дрон - 26.5.2008, 12:04


--------------------
Да. Именно так.
PM   Вверх
Platon
Дата 26.5.2008, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1801
Регистрация: 25.4.2006

Репутация: 16
Всего: 40



Цитата(Дрон @  26.5.2008,  13:03 Найти цитируемый пост)
Или есть шанс, что потом они его вообще выкинут?

Именно, хотя уже какую версию этот stop тянется.
PM MAIL ICQ   Вверх
Дрон
Дата 26.5.2008, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(Platon @  26.5.2008,  12:19 Найти цитируемый пост)
Именно, хотя уже какую версию этот stop тянется. 

Эх... Хотя думаю, что всё равно не выкинут smile
Но мне, скорее всего, придётся всё-таки по кускам картинку грузить, благо все соответствующие методы для этого есть.
Главное, чтобы на быстродействие и память это не сильно влияло.


--------------------
Да. Именно так.
PM   Вверх
Maksym
Дата 26.5.2008, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 14
Всего: 62



Дрон
Думаю, нужно грузить картинку не метдами ImageIO, а каким-нибудь простым байтовым стримом, где ты в цикле выбирашь данные в буфер. Там есть возможность сделать любую проверку на каждой итерации и прерваться при необходимости. А потом, после окончания загрузки, целиком загруженные данные можно отдать в более высокоуровневые методы из ImageIO.
PM MAIL   Вверх
Дрон
Дата 26.5.2008, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(Maksym @  26.5.2008,  17:07 Найти цитируемый пост)
Думаю, нужно грузить картинку не метдами ImageIO, а каким-нибудь простым байтовым стримом, где ты в цикле выбирашь данные в буфер. Там есть возможность сделать любую проверку на каждой итерации и прерваться при необходимости. А потом, после окончания загрузки, целиком загруженные данные можно отдать в более высокоуровневые методы из ImageIO.

Там JPEG. Сам файл занимает, скажем, порядка 20-30 мегабайт и загрузить его в память -- один миг, проблема состоит в декодировании JPEG, которое и занимает основное время. Писать собственный декодер я пока не готов -- и так времени нет smile

Я уже различными хитростям смог оптимизировать остальные операции с картинками, осталось только забороть загрузку.

Это сообщение отредактировал(а) Дрон - 26.5.2008, 17:17


--------------------
Да. Именно так.
PM   Вверх
math64
Дата 27.5.2008, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Код

class StopException extends RuntimeException {}
intreface StopChecker {
  void stopCheck() throws StopException;
}
class StopCheckInputStream extends InputSteam {
  StopChecker checker;
  void setChecker(StopChecker checker) {
    this.checker = checker;
  }
  ...
  int read (...) {
    if (checker != null) checker.stopCheck();
    return super.read(...);
  }
  ...
}

class LoadImageThread extends Thread {
   BufferedImage image;
   void run() {
      try {
         StopCheckerInputStream is = new StopCheckerInputStream(...);
         is.setChecker(new StopChecker() { ... });
         image = ImageIO.read(is);
      } catch (StopException ex) {
         image = null;
      } 
   }
}

PM   Вверх
Дрон
Дата 27.5.2008, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



math64, это вроде не совсем то. Но в общем случае -- да, можно было использовать перегруженный InputStream, при условии что декодирование идёт вместе с чтением. А вот если сначала читается весь файл, а только потом декодируется, то этот способ не пойдёт -- как внутри устроен ImageIO я не знаю.

Свою проблему я решил даже проще -- как оказалось ImageReader из ImageIO умеет сообщать свой прогресс, и вот в обрабочик прогресса я и добавил проверку на то не был ли прерван поток.

Так что с потоками пока разобрался. Всем отвечавшим спасибо smile

Это сообщение отредактировал(а) Дрон - 27.5.2008, 13:48


--------------------
Да. Именно так.
PM   Вверх
COVD
Дата 27.5.2008, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

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


interrupt по моему представлению, прерывает не выполнение потока, а ожидание. Если поток стоит в wait(), то interrupt() его разбудит. Если же поток выполняет последовательность команд, например, вычисления в цикле, то  interrupt()  никакого эффекта не даст - у потока нет никакого внутреннего флага, который он бы проверял на каждом шагу. Это дело программиста - "плодить доп. логические переменные", если надо. И это компетенция программиста ставить проверку флага в правильном месте: например, поток открыл соединение, потом проверил флаг, и обнаружил команду  "умереть". Так перед смертью он должен открытое соединение закрыть. Освободить захваченные ресурсы.

PM MAIL   Вверх
Дрон
Дата 27.5.2008, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(COVD @  27.5.2008,  17:04 Найти цитируемый пост)
interrupt по моему представлению, прерывает не выполнение потока, а ожидание. Если поток стоит в wait(), то interrupt() его разбудит. Если же поток выполняет последовательность команд, например, вычисления в цикле, то  interrupt()  никакого эффекта не даст - у потока нет никакого внутреннего флага, который он бы проверял на каждом шагу.

Использование interrupt() избавляет от необходимости вводить дополнительную булевую переменную, потому что у потока есть метод isInterrupted() позволяющий проверить, требуется ли прервать выполнение.



--------------------
Да. Именно так.
PM   Вверх
mindflyer
Дата 28.5.2008, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 113
Регистрация: 20.10.2004
Где: Smolensk, Russia

Репутация: 1
Всего: 4



Цитата(Дрон @  27.5.2008,  18:02 Найти цитируемый пост)
Использование interrupt() избавляет от необходимости вводить дополнительную булевую переменную, потому что у потока есть метод isInterrupted() позволяющий проверить, требуется ли прервать выполнение.

Иногда лучше всё же добавлять свою переменную. Уже писал где-то на форуме - столкнулся с ситуацией, когда interrupt перехватывался в сторонней библиотеке, обрабатывался и сбрасывался флаг. В итоге, если interrupt был вызван, когда управление было не в моём коде, а в коде той библиотеки, то мой код вызывая inInterrupted() получал false и продолжал выполнение.
PM MAIL ICQ   Вверх
Дрон
Дата 28.5.2008, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 6
Всего: 93



Цитата(mindflyer @  28.5.2008,  11:47 Найти цитируемый пост)
Уже писал где-то на форуме - столкнулся с ситуацией, когда interrupt перехватывался в сторонней библиотеке, обрабатывался и сбрасывался флаг.

Хм. А вот это действительно возможно.


--------------------
Да. Именно так.
PM   Вверх
COVD
Дата 28.5.2008, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата(Дрон @ 27.5.2008,  18:02)
..потому что у потока есть метод isInterrupted() ..

Спасибо, совсем забыл.

Цитата

столкнулся с ситуацией, когда interrupt перехватывался в сторонней библиотеке, обрабатывался и сбрасывался флаг


Это просто вредительство smile.  А как это возможно - сбросить флаг? У потока вроде нет метода setInterrupted. Как можно разентерраптить?
PM MAIL   Вверх
AlexeyVorotnikov
Дата 28.5.2008, 16:39 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 18.6.2007
Где: Москва

Репутация: 10
Всего: 18



Цитата(COVD @ 28.5.2008,  16:49)
Цитата(Дрон @ 27.5.2008,  18:02)
..потому что у потока есть метод isInterrupted() ..

Спасибо, совсем забыл.

Цитата

столкнулся с ситуацией, когда interrupt перехватывался в сторонней библиотеке, обрабатывался и сбрасывался флаг


Это просто вредительство smile.  А как это возможно - сбросить флаг? У потока вроде нет метода setInterrupted. Как можно разентерраптить?

У потока так же есть метод
public static boolean interrupted()
в описании которого сказано:
Цитата

Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. In other words, if this method were to be called twice in succession, the second call would return false (unless the current thread were interrupted again, after the first call had cleared its interrupted status and before the second call had examined it).



--------------------
RTFM!
Три источника и три составные части Java: The Java Language Specification, Java Platform API Specification, The Java Virtual Machine Specification
PM MAIL   Вверх
COVD
Дата 28.5.2008, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



 smile 

Спасибо.
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0777 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.