2017-02-17 12 views
0

1つのファイルを入力として処理し、SQLiteデータベースに書き込むマルチスレッドアプリケーションをデバッグしようとしています。SQLException:すべてのリソースを閉じてもデータベースがロックされています

私は4つのスレッドを作成し、各スレッドは別々の.dbファイルに書き込みを行い、同期/ファイルアクセスの問題を防ぎます。私はデータベースを取得しているという事実にもかかわらず私は私がそれらを完了した後に開いているすべてのリソースを明示的に閉じることに加えてリソースを試して使用しているにもかかわらず、エラーがロックされています。ここでは(スレッド・オブジェクトの内部に)私のコードは次のとおりです。

public void run() { 
    String path = database + num + ".db"; 
    try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + path); 
     PreparedStatement insertReview = conn.prepareStatement("insert into reviews (" + 
       "reviewerID, " + 
       "asin, " + 
       "rating, " + 
       "title, " + 
       "content, " + 
       "helpfulVotes, " + 
       "totalVotes) values (?1, ?2, ?3, ?4, ?5, ?6, ?7);");) { 
     System.out.println("Writing from thread " + num); 
     Class.forName("org.sqlite.JDBC"); 
     int x = 1; 
     for (Object[] review : reviews) { 
      insertReview.setString(1, (String) review[0]); 
      insertReview.setString(2, (String) review[1]); 
      insertReview.setDouble(3, (Double) review[2]); 
      insertReview.setString(4, (String) review[3]); 
      insertReview.setString(5, (String) review[4]); 
      insertReview.setInt(6, Integer.parseInt((String) review[5])); 
      insertReview.setInt(7, Integer.parseInt((String) review[6])); 
      insertReview.addBatch(); 
      //System.out.println("Processed review " + x + " of " + reviews.size() + " in " + num); 
      x++; 
     } 

     conn.setAutoCommit(false); 
     System.out.println("Executing batch in " + num); 
     insertReview.executeBatch(); 
     insertReview.close(); 
     conn.commit(); 
     conn.close(); 
    } 
    catch (Exception e) { 
     System.out.println("Thread" + num); 
     e.printStackTrace(); 
     System.exit(1); 
    } 
} 

あなたが見ることができるように、私は「資源としてみてください」との接続やプリペアドステートメントを開き、試してみるの最後にそれらの両方を閉じますブロック。私が呼んラインに私を指すのいずれか

java.sql.SQLException: database is locked 

:何が起こるかというと、プログラムが(、スレッドが作成された状態で実行し、そして死ぬ)しばらくの間、正常に動作してから私は、一見ランダムにこれを買ってあげるということです私はプリペアドステートメントを作成する試み宣言、およびスレッド内の

insertReview.executeBatch(); 

または

conn.commit(); 

またはライン例外がスローされているだけでなくランダムに表示されます。

なぜ私は、私がもはやそれを必要としなくなったらすべてのリソースを閉鎖していると私は肯定的です。

編集:私は、例外が一見無作為にスローされていることを強調したいと思います。時にはスレッドがバッチを実行しようとすると最初にスローされます。例外がスローされるまで、プログラムは問題なしで実行されます(プロセス内のスレッドの作成、すべてが正常に実行されます)。これまでにプログラムによって処理されたデータの量(0から60,000までのエントリ)には関連していません。

+0

try-with-resourcesブロックで明示的に接続を閉じる必要はありません。 –

+0

@Andy私はそれを実現しますが、リソースを試してみるとエラーがスローされてしまったので、私は安全にしました。 – theasianpianist

+1

「ロックされている」とは、他の誰かが同じデータベースにアクセスしていることを意味します。各スレッドが独自の.dbのみを使用していることを確認していますか? –

答えて

0

executeBatch()とcommit()が両方とも同期関数であることを確認してください...また、データベースをシリアル化またはマルチスレッドモードに設定することもできます。

関連する問題