1

Я передаю свою программу более чем 600 ссылкам, хранящейся в ArrayList, чтобы получить название веб-страницы, используя JSoup (среди прочих). Для каждой ссылки (используя для цикла) я создаю новый поток (используя thread.start()) и передаю ссылку через мою программу, я жду, пока мой поток завершится (с thread.join) перед запуском нового потока (одновременное выполнение вызовет некоторые проблемы, я сделал это, чтобы предотвратить неожиданный конец потока, чтобы остановить выполнение для других ссылок).Почему SocketTimeoutException заставляет мою программу замерзать?

Проблема в том, что иногда JSoup выбрасывает исключение SocketTimeoutException (которое я должен уловить), что заставляет меня замораживать мою программу. Я не знаю, почему выполнение останавливается даже в окружении try/catch.

Вот часть моего кода, возможно, может помочь вам понять:

// In the method actionPerformed() of my JPanel 

for(final String link : links) 
{ 
    Thread t = new Thread() 
    { 
     public void run() 
     { 
      Analyzer.process(link); 
     } 
    }; 
    t.start(); 
    try 
    { 
     t.join(); 
    } 
    catch (InterruptedException e) 
    { 
     e.printStackTrace(); 
    } 
} 

И в моем процессе:

// method process() of my Analyzer class 
try 
{ 
    Document doc = Jsoup.connect(lien).userAgent("Mozilla").timeout(5*10000).get(); 
    //     ^EXCEPTION THROWN HERE !^

    title = doc.title(); 
} 
catch (Exception e) 
{ 
    e.printStackTrace(); 
    erreurs+="Erreur lors de la lecture du titre\n"; 
} 

Это раздражает, потому что процесс ооочень долго, я смочите на ночь, и найти сегодня, что моя программа застыла на 54-й ссылке. ^^ 'Спасибо заранее!

EDIT - ОБНОВЛЕНИЕ

SercanOzdemir предложил мне использовать ExecutorService, вместо того чтобы создавать темы и сделать старт() - Join(), так что я пробовал:

ExecutorService ex = Executors.newSingleThreadExecutor(); 
for(final String link : links) 
{ 
    System.err.println("-- "+i+" --");    //DEBUG 
    ex.execute(new Runnable(){ 
      @Override 
      public void run(){ 
       try 
       { 
        Analyzer.process(link); 
       } 
       catch(Exception e) 
       { 
        e.printStackTrace(); 
       } 

      } 
    }); 
    i++;           //DEBUG 
    } 
ex.shutdown(); 

Но он печатает только мой отладочные ссылки. Любая идея, почему он не запускает мой процесс?

+0

В. Что именно является точкой начала потока только для того, чтобы сразу же «join()», не делая ничего другого между ними? А. Нет. – EJP

+0

@EJP Если я использую только один поток для выполнения моего процесса на 600 ссылках, единственное прерывание потока остановит весь процесс (у меня уже была эта проблема), и если я не буду выполнять каждый процесс один за другим, У меня другая проблема (особенно для обработки некоторых файлов). Я понимаю, что вы думаете, но это был единственный способ найти проблему с моими знаниями. :) – Malik

ответ

1

Я не пробовал это с помощью jsoup, но это простой способ создания потоков для выполнения задачи и контроля их состояния.

ExecutorService executorService = Executors.newCachedThreadPool(); 
    Future future = null; 
    for(final String link : links) 
    { 
     future = executorService.submit(new Runnable(){ 

     @Override 
     public void run(){ 
      try{ 
       Analyzer.process(link); 
      } 
      catch(Exception e){ 
       e.printStackTrace(); 
      } 

     } 
    }); 

     while(future != null 
       && !future.isDone() 
       && !future.isCancelled()) 
     { 
      try { 
       Thread.sleep(2000); // Or do something else 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

    } 

    executorService.shutdown(); 

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

ExecutorService ex = Executors.newSingleThreadExecutor(); 
for(final String link : links) 
{ 
    System.err.println("-- "+i+" --");    //DEBUG 
    ex.execute(new Runnable(){ //Here it is created 
     @Override 
     public void run(){ 
      try 
      { 
       Analyzer.process(link); 
      } 
      catch(Exception e) 
      { 
       e.printStackTrace(); 
      } 

     } 
}); 
i++;           //DEBUG 
//a split second later this loop finishes and overwrites the service again 
} 
ex.shutdown(); 
+1

То, что цикл является довольно уродливым решением ... Просто вызовите executerService.awaitTermination() – Victor

+0

Уродливо, но executerService.awaitTermination(); полезен, если он не имеет ничего другого в основной теме. Если его программа на основе пользовательского интерфейса, он может обновлять строку состояния и т. Д. –

+0

@Victor Это хорошо работает с циклом whil, возможно, было бы лучше использовать 'awaitTermination()', однако он имеет 2 параметра, поэтому метод принимает: ' executorService.awaitTermination (long, TimeUnit) ', так что мне лучше передать в качестве параметров в моем случае? – Malik

1

Открытие новой темы для каждой ссылки - очень плохой вариант.

Рассмотрите возможность использования ExecutionService, если вы хотите использовать программу с несколькими потоками.

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

new Runnable(){ 

      @Override 
      public void run(){ 
       try{ 
        // your codes 
       } 
       catch(Exception e){ 
        e.printStackTrace(); 
       } 

      } 
     }.run(); 
+0

Я не знал о существовании ExecutionService. Я не знаю, как это работает, но это кажется очень многообещающим, так как я мог взаимодействовать с моей JPanel, поэтому я предпочел бы использовать этот параметр.Поэтому я создаю новую службу-исполнителя за пределами цикла for («ExecutorService ex = Executors.newSingleThreadExecutor();»), тогда в моем цикле я бы написал: «ex.execute (new Runnable() {[...] }); 'и после моего цикла, закрываясь с помощью' ex.shutdown() ', это правильно? – Malik

+0

И добавьте ex.waitForTermination() 'или некоторые из представленных задач могут не выполняться. – Victor

+0

Кроме того, если ваш рабочий реализует Callable вместо Runnable, вы можете легко вернуть результат операции. – Victor

Смежные вопросы