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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Выполнение методов класса в отдельном потоке, Нужны предложения по реализации 
:(
    Опции темы
sergakrem
  Дата 29.8.2006, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 28.7.2006
Где: Украина, г. Киев

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



Всем, доброе время суток.

Подскажите пожалуйста ответ на следующий вопрос:

Есть некоторый класс, один из методов которого выполняет достаточно ресурсоемкую и длительную опреацию (вызвая толпу других методов и т.д.). Нужно следить за статусом выполнения этого метода на веб-странице. Для этого создана сама страница и сервлет, который будет заниматься опросом. 
Но так же стоит задача управлением выполнения этого кода (реализовывающего метод), я имею ввиду - старт, пауза, resume и стоп.

Т.е. необходимо, выполнить данный код в потоке, который можно запустить, остановить, и т.д.
Сам код (содержимое метода) был написан таким образом, что его достаточно сложно модифицировать для грамотной реализации управления состояниями, т.е. хотелось бы просто выполнять его в потоке в том виде, в котором он есть.

Я решал это приблизительно таким образом:

Код

  private void processSearch(final boolean forward) {

    Thread thread = new Thread(new Runnable() {
      Log procLog = LogFactory.getLog(this.getClass());
      public void run() {
    if (forward) { // Processing to forward ==================================
              ...
    } else { // Processing to backward ====================================
              ...
    }
      }
    });
  }



(Здесь все, что находится внутри public void run() { ... } собственно и есть само тело метода)


У Thread методы suspend(), stop() и resume() объявленны, как Deprecated - соответственно, не  хотелось бы ими пользоваться, хотя они по-видимому решили бы задачу.

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


Заранее, большое спасибо.

Это сообщение отредактировал(а) sergakrem - 29.8.2006, 17:25
PM MAIL ICQ   Вверх
Stampede
Дата 29.8.2006, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

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



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

Код

public class Search implements Runnable {
  public static int PAUSE = 1;
  public static int RESUME = 2;
  public static int STOP = 3;

  private int flag;

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

  public synchronized void setFlag(int flag)
  {
    this.flag = flag;
    notifyAll();
  }

  public void run() {
  // здесь выполняется собственно процедура
  }
}


Что касается реагирования на флажки, то тут придется выделять фрагменты кода, представляющие более или менее законченную операцию, и по окончании каждой из них проверять значение флага и соостветственно предпринимать какие-то действия. Хорошо, если какая-то продолжительная операция выполняется в циклле - тогда проверку флага можно вставить внутрь тела цикла.

Тут может возникнуть вопрос: а зачем, собственно, весь этот геморрой? Чем были плохи ныне упраздненные методы pause(), resume() и  stop()?

Плохи они тем, что позволяют любому внешнему процессу весьма авторитарным образом (например, по инициативе юзера) вмешиваться в ход выполнения процедуры, будучи при этом абсолютно ни уха ни рыла в том, что именно в нем происходит. А происходить может все что угодно, в том числе достаточно деликатные операции, которые блокируют всякие другие ресурсы.

Так вот, посольку только сам поток знает, когда он может безопасно приостановиться/завершиться, и какие действия при этом следует выполнить, чтобы не подвесить всю систему, то ему, как говорится, и все карты в руки. А мы, как сущности достаточно посторонние, можем только в мягкой форме выразить пожелание об изменении его состояния.

Таким образом, на смену авторитарному стилю управления потоками пришел более мягкий, демократический. Я бы назвал его методом делегирования полномочий. В этом, по-видимому, нашел отражение тот факт, что менеджеры среднего звена в IT-индустрии таки действительно очень мало смыслят в технологических тонкостях создаваемых продуктов, и если командный стиль годится в армии или там где-нибудь на буровой, то в таком тонком деле как создание ПО на девелоперов лучше все-таки не давить, а предоставить им относительную свободу реализации smile



--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
sergakrem
Дата 31.8.2006, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 28.7.2006
Где: Украина, г. Киев

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



Ok. Спасибо за ответ.
Хочу тогда посоветоваться по этому поводу

Цитата

...
Плохи они тем, что позволяют любому внешнему процессу весьма авторитарным образом (например, по инициативе юзера) вмешиваться в ход выполнения процедуры, будучи при этом абсолютно ни уха ни рыла в том, что именно в нем происходит. А происходить может все что угодно, в том числе достаточно деликатные операции, которые блокируют всякие другие ресурсы.


Т.е. я правильно понимаю - если я (как разработчик) знаю, что в моем коде (в данном случае в этом методе, который я хотел бы выполнять в потоке) не происходит никаких блокировок и других "деликатных" smile вещей, и в принципе - я могу ограничить логику использования этих методов - то при их использовании никакого вреда не будет (за исключением, простите, матюков компилятора об использовании deprecated методов)?


Хотя я вобщем-то подумал еще об одном способе - блокировать синхронизированный объект (если мне надо остановить выполнение кода), который повсеместно там используется в коде, и соответственно - отпускать его (если я хочу продолжить выполнение). Ну а остановка выполнения (функция stop) - просто прибивать ссылку на объект потока (хотя на сколько я помню - это не поможет), ну или какой-нибудь другой способ.

Это сообщение отредактировал(а) sergakrem - 31.8.2006, 19:11
PM MAIL ICQ   Вверх
Stampede
Дата 31.8.2006, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

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



Цитата(sergakrem @  31.8.2006,  10:09 Найти цитируемый пост)
Хотя я вобщем-то подумал еще об одном способе - блокировать синхронизированный объект (если мне надо остановить выполнение кода), который повсеместно там используется в коде, и соответственно - отпускать его (если я хочу продолжить выполнение).


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

Что я имею в виду? Ну прежде всего то, что логику, использующую блокировки, очень непросто писать и еще труднее отлаживать. Как минимум нужно очень хорошо представлять себе, как работают мониторы объектов и все, что с ними связано (например, поведение при повторном вхождении в синхронизированный участок кода). Так вот, даже если ты запрограммируешь все это дело и оно вроде как заработает, не факт что под нагрузкой не начнут вылазить всякие разные странности. Потому что, повторяю, смоделировать все возможные сценарии переходов состояний на этапе тестирования - задача в общем случае очень нетривиальная.

Поэтому если сравнивать варианты, я бы наверное лучше тупо в лоб задействовал "устаренные" методы - если, как ты говоришь, ты уверен, что ничего страшного при этом не произойдет. Хотя, конечно, трудно советовать что-то конкретное, не зная подробностей. Что хоть за задача-то? Если не военная тайна, конечно smile

Цитата(sergakrem @  31.8.2006,  10:09 Найти цитируемый пост)
Ну а остановка выполнения (функция stop) - просто прибивать ссылку на объект потока (хотя на сколько я помню - это не поможет)


Дак именно что не поможет! Если извне ничего не делать, то поток будет мослать до тех пор пока не дойдет до конца метода run(). Коль скоро ты не хочешь влезать внутрь готового кода, можно опять же насильно вызвать stop(), но в этом случае по крайней мере нужно оформить действия по освобождению ресурсов в виде конструкции try-finally:

Код

public void run() {
  try {
    // собственно код процедуры
  }
  finally {
    // действия по завершению
  }
}


Ди, и вот еще что я подумал. Какие-то смутные подозрение вызывает твое упоминание о том, что код процедуры содержит кучу синчронизованных участков. С чего бы это они там были? Ты точно уверен, что ничего не подвесишь прямыми вызовами suspend()?



--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
sergakrem
Дата 31.8.2006, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 28.7.2006
Где: Украина, г. Киев

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



Да задача-то конечно - не военная тайна. 
Просто она вряд ли будет сама по себе интересна. Эта веб-прога просто является фронт-эндом к одной системе, к которой у меня есть интерфейс через JNI.

Идея такая - есть объект (методы которого я хочу выполнять в потоке), который просто дергает за native функции, получает оттуда некоторые данные, приводит их в нужный вид а затем передает их на формирование вида в JSP.

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

Просто дело в том, что перед выполнением этого метода объект некоторое время действиями пользователя на странице инициализируется начальными данными, а только затем уже, их используя, обрабатывает результаты native функций, которые он потом дергает.

Я вот, собственно, о чем и подумал - я же могу для каждого такого выполнения создавать один такой объект, который никак не связан с себе подобными - и выполнять его "длинный" метод в бэкграунде, а пользователю в это время давать возможность уже создавать и настраивать (инициализировать) следующий объект, для следующего исполнения.
PM MAIL ICQ   Вверх
COVD2
Дата 2.9.2006, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата

Тут может возникнуть вопрос: а зачем, собственно, весь этот геморрой? Чем были плохи ныне упраздненные методы pause(), resume() и  stop()?

Плохи они тем, что позволяют любому внешнему процессу весьма авторитарным образом (например, по инициативе юзера) вмешиваться в ход выполнения процедуры, будучи при этом абсолютно ни уха ни рыла в том, что именно в нем происходит. А происходить может все что угодно, в том числе достаточно деликатные операции, которые блокируют всякие другие ресурсы.

Так вот, посольку только сам поток знает, когда он может безопасно приостановиться/завершиться, и какие действия при этом следует выполнить, чтобы не подвесить всю систему, то ему, как говорится, и все карты в руки. А мы, как сущности достаточно посторонние, можем только в мягкой форме выразить пожелание об изменении его состояния.


  Наверное, дело в том, что сам поток как раз и не знает. Если бы знал, то при поступлении команды, скажем, stop(), он бы мог продолжить выполнение до ближайшей безопасной точки и остановиться (или откатиться назад и снять, например, поставленную им блокировку smile ).  Безопасные точки знает программист. И в этих точках он может вставить код проверки состояния флага и описания действий потока.


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

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

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


 




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


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

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