Модераторы: 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   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

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

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


 




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


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

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