2016-02-09 2 views
0

Я пытаюсь запустить задачу периода из main() с помощью функций TimerTask на Java и запускать задачу run(). Код после таймера - это REPL. Код выглядит так:TimerTask hangs

public static void main(String[] asArguments){ 
    java.util.Timer timer = new Timer(); 
    long durationDelay_ms = 60*60*1000; // 1 hour 
    long durationPeriod_ms = 60*60*1000; // 1 hour 
    timer.scheduleAtFixedRate( // reload prices every hour 
     new TimerTask() { 
      @Override 
      public void run() { 
       StringBuffer sbError = new StringBuffer(); 
       if(! reload(false, sbError)){ 
        System.out.println("error reloading prices: "); 
       } 
       sbError = null; // garbage collect 
      } 
    }, durationDelay_ms, durationPeriod_ms); 

    // REPL 
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    while(true){ 
     System.out.print("> "); 
     try { 
      String s = br.readLine(); 
      \\ ... code to process command 
     } catch(Throwable t) { 
      \\ handle error 
     } 
    } 
} 

public static final boolean reload(){ 
    for(int i = 1; i <= 4; i++){ 
     String sURL = "c:\\xyz.com\\" + i; \\ URL I am reading from 
     System.out.println("retrieving data from:\n" + sURL); 
     StringBuffer sb = new StringBuffer(10000); 
     try { 
      URL url = new URL(sURL); 
      HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
      sb = readStream(con.getInputStream()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
    System.out.println(sb.toString()); 
} 

Задача пытается сделать несколько URL-соединений и распечатать ответ каждого из них. Что происходит на практике, так это то, что сообщение «получение данных из ...» появляется один раз, тогда задача, похоже, зависает. Если я использую REPL, набрав команду в StdIn, в stdout появятся ошибки «время ожидания соединения».

Итак, TimerTask, похоже, как-то противоречит REPL (который блокирует readline). Что здесь происходит?

ответ

0

java.util.TimerTask имеет только задачу для запуска. Если одна задача продолжает работать, другие задачи должны ждать, пока она закончится. Вы можете заменить его java.util.concurrent.ScheduledExecutorService, он может запустить еще нить для выполнения задачи ...

Я думаю, URL, который вы пытаетесь подключиться требуется какой-то «вход», поэтому он ждет дополнительных данных ... Попробуйте изменить исходный код и предоставить ему некоторые данные. Например:

HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
    con.setConnectTimeout(5000);//not required 
    con.setDoOutput(true); 
    con.setDoInput(true); 
    OutputStream out = con.getOutputStream(); 
    out.write("&param1=a&param2=b".getBytes()); 
    out.close(); 
    sb = readStream(con.getInputStream()); 
+0

Здесь нет проблем с перекрытием задач. Период таймера составляет 1 час, поэтому конфликт задач не возникает. Выполняется первая задача FIRST. –

0

В итоге у меня возникла проблема. Реализации метода HttpURLConnection openConnection синхронизируются на внутреннем объекте с именем streamHandlerLock, который совместно используется группой различных внутренних библиотек Java, включая буферные библиотеки чтения.

Это в основном означает, что вы не можете использовать IO с потоковым использованием, используя java.net или java.io в нескольких параллельных потоках.

В моем случае, что происходит, REPL блокирует BufferedReader.readLine(), поэтому streamHandlerLock заморожен. Таким образом, когда openConnection выполняет его блокировки на этом объекте.

(я мог бы что-то сказать о навыках кодирования Джеймса Гослинга, который разработал и написал эту систему borked up и подписал свое имя на исходный код, или я мог бы сказать что-то о полном отказе команды Sun Oak перепишите этот мусор, когда Java перешла в основное русло в 2000 году, 16 лет назад, но, я думаю, я оставлю его читателям воображение, что я могу сказать.)