2016-03-24 9 views
2

このようなJavaに関するいくつかの質問がありますが、誰も私が見つけた回答を受け入れておらず、私の状況はもう少し具体的です。私は、ファイルを1つずつ処理するプログラムを持っています。時には、ファイルが私のプログラムに見えるようになってから、プログラムが数秒間それらを落とすことによって、ファイルが使用中にロックされたままになることがあります。私はそのプログラムを支配していません。私のプログラムでは、プログラムがそのファイルを読み込もうとしているときにファイルが使用中であれば、すでにエラー処理をしています。ファイルが完全にスキップされます。私が実装したいのは、ファイルが数秒後にロック解除されるかどうかを調べるための再試行スキームです。ここでの別の質問では、FileUtils.touch()を使用するよう提案しました。プロジェクトで既にFileUtilsを使用しているので便利です。 javadocによると、FileUtils.touch()はファイルが別のプロセスで使用されている場合はIOExceptionとなります。いいね。しかし、私が言いました答えの下のコメントの1つは、何の説明もなしに競合状態を警告しました。ここで私が導入を検討していたコードです:ファイルロックがリリースされるのを待っています

// Implementing Sason's suggestion 
int retries = 0; 
while (retries < MAX_RETRIES) { 
    try { 
     processFile(file); 
    } catch (IOException ioe) { 
     // Assumes this is a file in use exception... bad thing? 
     log.warn("File is in use. Waiting 1 second to retry."); 
     retries++; 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException ie) { 
      log.warn("Thread interrupted while waiting for file lock to clear."); 
      break; 
     } 
    } 
} 

私は、ファイルがFileUtils.touch(間再びロックになることができることを実現)とprocessFile()メソッド呼び出しは(と私はそれが競合状態が中程度警告していると推定します私が見つけた受け入れられない答え)でも、それは問題ありません。 processFile()メソッドは、現在のようにロックエラーを処理します。この場合、ファイルが別のプロセスによって開かれても問題ありませんが、ロックすることはできません。

また、ファイルが1,2秒後にロック解除されることがありますが、ファイルを削除するプログラムによってロックが無期限に保持される場合もあります。また、同じファイルを再処理しようとすると、再試行が終わった後にファイルを処理できなかったときに送信者に通知できるようにする必要があります。

ここに何か不足していますか?これを行うにはより良い/より安全な方法がありますか?

+0

'touch()'は、ファイルが開いているかどうかをテストする信頼できる方法です。特定のプロセスがファイルを書き込んでいる特定のシステムで動作するかもしれませんが、それは問題ありませんが、コードをどこか別の場所で実行したり、ライターを変更した場合は、再テストして動作することを確認する必要があります。これを行う正しい方法は 'FileLock'ですが、それは書き込みプログラムが基礎となるファイルシステムのロック機構を使うことを必要とします。 – erickson

+0

私は私の質問でもっとはっきりしていたはずです。ファイルがロックされていない別のプロセス(たとえば、NotePad ++など)でファイルが開いている場合は、問題ありません。 'processFile()'がファイルをロックしようとするためロックできません。私は 'FileLock'についてあなたの意見を見ていますが、あなたはかなりリファクタリングを必要とすることに間違いありません。私は 'touch()'は、別のプログラムがファイルをオープンしているがロックされていないかもしれないという同じ注意書きでクロスプラットフォームで動作すると思う。 –

答えて

3

私はSchedueledExecutorServiceを使用して、ファイルを処理しようとする遅延を伴う作業を送信します。処理が失敗した場合は、作業が成功するまで何度も何度も投稿してください。

ここにFileUtils.touchが必要ですか?なぜファイルを読み込もうとしないのですが、失敗した場合は再試行してみてください。

thread.sleepは醜いです。複数のファイルを処理する場合、それぞれのファイルは完了するまで独自のスレッドを使用する必要があります。 SchedueledExecutorServiceがより効率的になります。

+0

私は同意します。レースは、小切手と行動の間に原子性がないためです。ロックを取得できないためにアクションが失敗した場合、問題はありません。ちょうど後で試してください – erickson

+0

これは面白い考えです。私は考えていたものの、最初は拒否しました。ファイルが無期限にロックされたままになり、処理できないファイルにプログラムがループしてしまいます。エラー処理では、送信者にファイルが処理できず、ファイルが無視リストに追加されたという通知が提供されます。1日の終わりに、処理できなかったファイルのリストが送信者に送信されます。私は実際にその動作を変更したくないだけです。ファイルが使用可能になるまで数秒間待ってから、未処理のリストを終了したいだけです。 –

+0

また、Thread.sleep()は醜いですが、ファイルは同期して処理する必要があるため、処理する次のファイルをブロックしても問題ありません。私はほとんどの場合、ファイルを順番に処理する必要はありませんでした(できるだけ到着順序に近い)。それは、私があなたが言ったことを正確に行うことができ、特定の回数の再試行後に実行可能ファイル自体が期限切れになるため、実際にはかなり単純化されます。私は未来のを使うことさえできました。 –

関連する問題