2013-09-12 3 views
0

Я довольно новичок в программировании потоков на Java, и в настоящее время я создаю приложение, которое, помимо прочего, принимает несколько сценариев SQL и вызывает их.Проблема синхронизации с синхронизацией Java: PrintWriter медленнее, чем другие операции

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

Конечно, все это осуществляется с помощью цикла for.

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

Я пробовал свой путь, используя синхронизированные блоки кода, методы wait() и notify(), но пока не удалось. Я придаю отрывок кода:

boolean waiting_for_end_of_file_writing = true; 

    FileWriter fw = new FileWriter(FICHIER_LOG_ERREURS_SQL, true); 
    PrintWriter pw = new PrintWriter(fw); 

    for(int j = 0; j < input_paths_sql.length; j++){ 

     System.out.println("Script " + m + " dont " + input_paths_sql.length 
       + " avec nom " + oftp.get_locals()[j] 
       + " à exécuter"); 
     try { 
      Generic_library.Call_Fichier_SQL(oftp.get_locals()[j], 
        ojdbc.get_sybase_connection()); 
     } catch (IOException ex) { 
      Logger.getLogger(Form_table_clients.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (SQLException ex) { 
      pw.write("Exception en fichier " + oftp.get_locals()[j] + "\r\n"); 
      ex.printStackTrace(pw); 
      pw.write("\r\n"); 
      Logger.getLogger(Form_table_clients.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     m++; 
    } 
    synchronized(pw){ 
     pw.write(" ----------------- END OF UPDATE PROCESS ----------------- \r\n"); 
     waiting_for_end_of_file_writing = false; 
     pw.notify(); 
     } 
    synchronized(pw){ 
     try { 
      while(waiting_for_end_of_file_writing) 
       pw.wait(); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(Form_table_clients.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
    return success; 

Так что это идет: - Generic_library.Call_Fichier_SQL() принимает путь и объект подключения к базе данных, и использует их с CallableStatement для вызова скрипта

Моя цель состоит в том, чтобы остановить поток перед поступлением в линии «вернуть успех» который заканчивает метод, пока не PW завершены все написанные и в конце концов выполнила линию, которая идет

pw.write (»--- -------------- EN D ПРОЦЕССА ОБНОВЛЕНИЯ ----------------- \ r \ n ");

В противном случае файл журнала, как указано выше, заканчивается неполным.

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

+0

Как сказал @PeterLawry, вам необходимо очистить PrintWriter, который имеет внутренний буфер. Но лучшим решением является замена PrintWriter на реальную структуру ведения журнала, такую ​​как Log4J или LogBack. – kdgregory

ответ

0

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

Короче говоря, всегда закрывайте Stream/Reader/Writer/Statement/Connection/ResultSet, когда вы закончите с ними. (На самом деле ничего, что может быть близко())

В вашем случае я бы удалить оба синхронизированные блоки и использовать pw.flush();

Хотя Println() не является быстрым, он должен быть в 10 раз - 100x быстрее, чем SQL запрос из базы данных JDBC.

+0

Работает. Такой долгое время просто оглядывался, чтобы найти такой простой ответ: -/ Спасибо, миллион, @PeterLawrey и kdgregory –