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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Один поток ждет выполнения другого... 
:(
    Опции темы
OlegRu
Дата 13.12.2005, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



1. Из второго потока идет коннект к серверу, в итоге возвращается некая строка.
2. Эта строка должна отобразиться в первом потоке путем disp.setCurrent(tb);
3. Кажись, надо расставить здесь synchronized, wait() и notify(), но не знаю как?!
Подскажите, пожалуйста.

Код

public class  Main extends MIDlet implements CommandListener 
{    
     ...
    public Main(){
     ...
    }
          
    public void commandAction(Command c, Displayable d){
         if (c == connect)
         {   
            disp.setCurrent(WaitForm);
            s = new [b]MyNetworkSession();[/b]
            s.start();

    // [b]То, что ниже, выполняется гораздо быстрее чем то, что выше[/b]
    // [b]Как сделать так, чтобы нижний блок ждал полного выполнения верхнего блока?[/b]
         {
                tb = new TextBox("Test.php", s.getText(), 256, 0);
                tb.setCommandListener(this);          
                [b]disp.setCurrent(tb);[/b]                         
              }
         }
      }    
}

/ **************

class MyNetworkSession extends GameCanvas implements Runnable {
   ...
public MyNetworkSession(){
   ...
}

   public void start() {  
      Thread T = new Thread(this);
      T.start();  
      stop=false;
   } 
    
    public void run() {
      try{
         Request(URL);
      }    
    catch (Exception e){
    } 
}

    public void Request(String url) throws IOException{        
    ...
    } 
}


Это сообщение отредактировал(а) OlegRu - 13.12.2005, 18:41
PM MAIL   Вверх
COVD
Дата 13.12.2005, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



s = new MyNetworkSession(this);
s.start();
synchronized(this){
wait();//ставим текущий поток в ожидание
}


...

private Main obj;
public MyNetworkSession(Main obj){
this.obj = obj;
...
}


public void run() {
try{
Request(URL);
synchronized(obj){
obj.notify(); //будим ждущий поток по завершении реквеста
}


}
catch (Exception e){
}
}


Это сообщение отредактировал(а) COVD - 13.12.2005, 19:57
PM MAIL   Вверх
Sardar
Дата 14.12.2005, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

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



COVD по моему ошибка с синхорнизацией,
Код
synchronized(this){
  wait();//ставим текущий поток в ожидание
}

Лочим на свой instance, внутри synchronized первый получивший тред уверен, что все остальные потоки будут блокироваться на этом обьекте, НО:
Код
synchronized(obj){
obj.notify(); //будим ждущий поток по завершении реквеста
}

получаеться второй тред залочиться на synchronized(obj) и будет ждать пока первый поток отпусит обьект (выйдет из synchronized). Так как первый поток ждёт события, от заблокированного второго получаем deadlock... хотя до концане уверен smile
Добавлено @ 01:33
Также задачу можно порешать вложенным классом, обьекто которог передадим MyNetworkSession. Вложенный класс будет играть роль listener'а события "готово" и возобновит работу. Всё может уложиться в одном потоке.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
OlegRu
Дата 14.12.2005, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



To COVD
Спасибо, я вроде понял суть в принципе. Сделал точно как вы написали.
To Sardar
А вы действительно правы, второй поток MyNetworkSession попадает в дедлок.
Появляется сообщение о разрешении подключиться к инету и приложение замирает в молчании smile
Что мне делать, как мне быть? smile
А можно поподробнее о том, как сделать все в одном потоке (если нельзя в разных).
Благодарю за ваше участие!

Код
       
public class Main extends MIDlet implements CommandListener
{ 
    ...
    private MyNetworkSession s;
    
    public Main(){
    disp = Display.getDisplay(this);
    game = new Canva(this);     
    }
   
    public void startApp(){ 
    ...
    }

    ...
    public void commandAction(Command c, Displayable d){
        if (c == account)
        { 
            URL="http://localhost/test.php?e=Account&id=68584576376";            
            s = new MyNetworkSession(this);
            s.start();
            try{
                 synchronized(this){
                     wait();//ставим текущий поток в ожидание
                 }
            }
            catch (Exception e){}
            
            Alert reg_alert = new Alert("Ваш счет", "",null,null);
            disp.setCurrent(reg_alert);
       }                         
    } 
}  // End of class Main


Код

class MyNetworkSession extends GameCanvas implements Runnable {
private String URL;
private Main obj;
        
public MyNetworkSession(Main obj)
{
    ...
    this.obj = obj;
    URL = obj.URL; 
}

public void start() {  
    Thread T = new Thread(this);
    T.start();  
}
        
public void run() {   
    try{
        Request(URL);
        synchronized(obj){
            obj.notify(); // будим ждущий поток по завершении реквеста
        }
    }    
    catch (Exception e){
    } 
}

public void Request(String url) throws IOException{        
     ...
} 

} // End of class MyNetworkSession

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


Эксперт
***


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

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



Цитата
по моему ошибка с синхорнизацией,


Нет, для wait и notify как раз так и надо делать, синхронизировать один и тот же обьект. В других случаях будет lock.

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


Новичок



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

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



To COVD
А мне что с потоками делать?
Сейчас в таком виде (выше) не работает. smile
PM MAIL   Вверх
COVD
Дата 14.12.2005, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



определите , в каком месте проблема возникает. Расставьте System.out.println("..."), чтобы определить последовательность выполняемых операций.
PM MAIL   Вверх
OlegRu
Дата 14.12.2005, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



To COVD
Да, я расставил, где надо, println, и оказалось, что вся работа виснет при входе в метод Request(String url), а именно после вызова Connector.open(url); Но раньше (без этой синхронизации) коннект шел без проблем.

Код

public void Request(String url) throws IOException
{            
    InputStream iStrm = null;
    int rc;

    try{
             System.out.println("Flag in Request");  // эту строку выводит
      con = (HttpConnection)Connector.open(url); 
             System.out.println("Flag in Request1"); // а после open(url) нет никакой жизни :(
      con.setRequestMethod(con.GET);      
      rc=con.getResponseCode();
      if ( rc== con.HTTP_OK)
      {
        String str;
        iStrm = con.openInputStream();
        int length = (int) con.getLength();
        if (length != -1)
        {
          byte serverData[] = new byte[length];
          iStrm.read(serverData);
          str = new String(serverData);
        }
        else
        {
          ByteArrayOutputStream bStrm = new ByteArrayOutputStream();       
          int ch;
          while ((ch = iStrm.read()) != -1)
            bStrm.write(ch);
  
          str = new String(bStrm.toByteArray());
          bStrm.close();                
        }   
        text="File Contents: "+str;
        System.out.println(text);
      }
    }
    catch (Exception e)
    {
        System.err.println("Msg: ERROR:");
        e.toString();
        e.printStackTrace();
        e.getMessage();
    } 
    finally 
    {
      if (iStrm != null) { iStrm.close(); }
      if (con != null) { con.close(); }
    }
} 

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


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

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





--------------------

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


Опытный
**


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

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



Во-первых: не уловил что это за метод такой в MyNetworkSession
Код

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


а кто тогда вызывается (public void run() или этот start()), когда делаем s.start(); из public void commandAction(Command c, Displayable d)

Во-вторых: добавь просмотр отлавливаемых Exception как в этом коде, я так думаю, туда попасть должен твой IOException из Request(String url) который у тебя стоит как throws, и поэтому он у тебя не попадёт в твой catch из Request метода
Код

public void run() {   
    try{
        Request(URL);
        synchronized(obj){
            obj.notify(); // будим ждущий поток по завершении реквеста
        }
    }    
    catch (Exception e){
           obj.notify();
           e.printStackTrace();
    } 




--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
OlegRu
Дата 15.12.2005, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ребята, спасибо за ваше внимание.
Значит-ца так. Я уже брожу два дня по инету в поисках решения проблемы и только-что наткнулся на это:
Topic: thread + connector.open
Оказывается, там тоже была некоторая проблема с одинаковым "корнем". Там человек жаловался на Connector.open(defaultURL), после которого у меня застывала программа.
Тогда пришла мысль полностью закомментировать код в методе Request(String url) и написать так:
Код

public void Request(String url) throws IOException
{            
    try{        
            // Это поставил специально чтоб "потянуть время"
           // Можно и цикл сделать длинный
            try { Thread.sleep(10000); } 
            catch (java.lang.InterruptedException e) {}

        text="File Contents: ";
        System.out.println(text);
    }
    catch (Exception ee)
    {
        System.err.println("Msg: ERROR:");
        ee.printStackTrace();
    } 
} 

Теперь потоки ЗАМЕЧАТЕЛЬНО синхронизируются!! Первый поток ждет, пока пройдут 10 секунд во втором потоке, последний возвращает строку "File Contents: " первому потоку. И первый поток отображает ее в своем Алерте.
Так что само устройство синхронизации потоков для этого случая, подсказанное COVD'ом, правильно на самом деле!
Единственная беда, я не знаю как же быть с самим Connector.open !!
Почему так происходит?? Или я еще не понимаю всей глубины происходящего!
Если кто хочет разобраться,- то давайте вместе. Мне это очень надо smile
PM MAIL   Вверх
Dancer
Дата 15.12.2005, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



а это не поможет?
Connector.open("http://ya.ru",Connector.READ, true);



--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
OlegRu
Дата 15.12.2005, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



To Dancer
Не, не помогает это.
PM MAIL   Вверх
Dancer
Дата 15.12.2005, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



я уже понял что не помогате, сейчас подекомпилил классы, так вот что обнаружил, этот параметр в конечном счёте игнорируется в методе, где происходит непосредственный коннект.
smile вот так то.....................


--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
OlegRu
Дата 15.12.2005, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



To Sardar
Получается, что вообще можно обойтись без синхронизации, например, так:

В классе Main:
Код

public void displayAlert() 
{
    Alert reg_alert = new Alert("dfh", s.text,null,null); 
    disp.setCurrent(reg_alert); 
}

В классе MyNetworkSession сразу после метода Request(String url):
Код

obj.displayAlert();

Я пробовал, так работает хорошо.


To Dancer
Я поставил Exception так:
Код

catch (Exception e){    
           obj.notify(); // <----    
           e.printStackTrace();    
    } 

но все равно не выдается мне почему-то текст ошибки.

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


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

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



Цитата(OlegRu @ 15.12.2005, 16:25)
Получается, что вообще можно обойтись без синхронизации

Да. Определись с задачей, нужны ли тебе два потока, первый ведь остановиться и будет ждать. Задача где реально нужно несколько потоков, это например загрузка файла под FTP с нескольких коннектов. Но и тогда можно передать ссылку загрузчикам на главное приложение, через которую они отдают инфу. При этом АПИ синхронизированно (synchronized методы), когда приходит последний кусок инфы, выполняем требуемое действие.

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


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
OlegRu
Дата 16.12.2005, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо всем за участие!
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.0639 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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