0

我对 Java 中的线程编程非常陌生,我目前正在构建一个应用程序,其中包括一些 SQL 脚本并调用它们。

对于每个文件,它都会执行调用,如果抛出一些异常,它会捕获它并使用由 FileWriter 构造的 PrintWriter 将相关信息写入日志文件。

当然,所有这些都是由 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() 将路径和 Connection 对象带到数据库,并将它们与 CallableStatement 一起使用来调用脚本

我的目标是在线程到达“返回成功”行之前停止线程,该行完成该方法,直到 pw 完成所有写入并最终执行该行

pw.write(" ----------------- 更新过程结束 ----------------- \r\n");

否则,如前所述,日志文件最终会不完整。

感谢您能给我的任何帮助。同样,如果有人能想出一些绕过问题的想法(例如,可能是通过使用某种线程安全的方式写入文件),它也可以做到。

4

1 回答 1

0

当你写完后,你需要刷新它,或者最好 close() 它。如果您让应用程序保持运行,它可以刷新和清理资源本身(在某个随机时间),但您应该始终自己执行此操作,以便您知道它已完成。

简而言之,当你完成它们时,总是关闭 Stream/Reader/Writer/Statement/Connection/ResultSet。(实际上任何可以 close() 的东西)

在你的情况下,我会删除两个同步块并使用pw.flush();

虽然 println() 并不快,但它应该比来自 JDBC 数据库的 SQL 查询快 10 到 100 倍。

于 2013-09-12T11:07:07.203 回答