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

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

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


 




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


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

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