0

次のことを行うマルチスレッドプログラムがあります。

thread_1作成された新しいファイルを検出するためのハードディスクのリスナーです。Java 7 で apiを使用WatchServiceします。別のプログラムによって新しいファイルが作成されるthread_1と、それを検出して取得し、PriorityBlockingQueueex に配置します。

priorityBlockingQueue.add(FileObject)

FileObjComparatorカスタムオブジェクト実装コンパレータです。I get from system time when detect this fileの作成時間とfileCreatedTimeフィールドでソートされます。FileObject

 public int compare(FileObject o1, FileObject o2) {
        return o1.getFileCreatedTime().compareTo(o2.getFileCreatedTime());
    }

priorityBlockingQueue次のように初期化されます。

DataFileQueue.priorityBlockingQueue = new PriorityBlockingQueue<FileObject>(100000, new FileObjComparator());

Thread_2これは、このファイルの最後のファイルの次に処理されます。priorityBlockingQueue

if(priorityBlockingQueue.size) > 1)
   process(priorityBlockingQueue.poll());

2 つのスレッドが並行して実行されていますが、多数の大きなファイルを処理すると、書き込み中にファイルをThread_2処理することがあります。これは、コンテンツ ファイルと処理結果を再確認することで検出されます。

このプログラムは Centos 6.2 で実行されており、このハードディスク パーティションは非同期モードでマウントされています。助けてくれてありがとう。

4

4 に答える 4

2

最後から2番目のファイルを実際に処理している場合、複数のプロセスまたはスレッドが入力ファイルを生成していない限り、ファイルのサイズが大きくなっていることに驚いています。次のファイルを書き込む前に、ファイルを作成している他のプロセスが各ファイルをフラッシュして閉じていることを確認してください。

  • ファイルをブロック単位で読み取り、一定期間さかのぼってファイルに追加データが追加されたかどうかを確認し、その時点でRandomAccessFile. ファイルを 1 行ずつ読んでいる場合は、残念ながら独自のページネーションを行う必要があります。ファイルが行ベースの場合は、行末文字でファイルが閉じられていることを確認する必要があります。

  • もう 1 つの方法は、ファイル システムがバッファをフラッシュできるように、ファイルの処理を少し遅らせることです。醜くて信頼できないが、必要かもしれない。

  • 出力プロセスを調整できる場合は、ファイルをマジック ストリングで終了し、マジック ストリングが表示されるまでファイルを処理しないようにすることができます。

  • ファイルを書き込むプロセスを実行し、ファイルのサイズを「.size」拡張子(または何か)が付いた別のファイルに書き込むことができます。サイズ ファイルは、正しい文字数を読み取っていることを確認するのに役立ちます。

  • Runtime.exec("/bin/sync");~unix システムで実行している場合は、ファイルからの読み取りを開始する前に、ファイル システムを同期することも試してください。問題は、これのサポートが OS に大きく依存していることです。また、実際のパフォーマンス キラーになる可能性もあります。彼は私の Mac の man ページです。

    同期ユーティリティを呼び出して、すべてのディスク書き込みが完了したことを確認できます

于 2012-07-04T16:55:32.973 に答える
1

一度に複数のスレッドによってファイルが書き込まれないように、セマフォを使用して各ファイルへのアクセスを整理することができます。各ファイルオブジェクトには独自のセマフォが必要であり、各スレッドはファイルに書き込む前にセマフォを取得しようとする必要があると思います。

于 2012-07-04T16:46:26.587 に答える
0

Comparator は、作成時間ではなく、最終変更時間で並べ替える必要があります。たとえば、A、B の順序で開かれた 2 つのファイルが完全に同じ順序で書き込まれることをどのように知ることができるかわかりません。あなたはそう言っていません。

于 2012-07-07T02:48:38.463 に答える
-2

より詳細な回答を編集します。

問題は ...

あなたが書いた

このファイルを検出したときにシステム時間から取得した FileObject の作成時間と fileCreatedTime フィールドでソートされます: ....

thread_1 は、作成された新しいファイルを検出するためのハードディスクのリスナーです。Java 7 では WatchService API を使用しています。別のプログラムによって新しいファイルが作成された場合。... thread_1 はそれを検出して取得しそれを PriorityBlockingQueue ex に入れます:

  • 作成時間と「ファイル書き込み終了時間」は大きく異なる場合があります。(ファイルサイズにもよります)。

例えば:

ファイルマネージャーを開きます。約 60 mb のファイルのダウンロードを開始します。作成時間に注意してください。約3分後、最終時間を見てください。

新しいファイルを検出するために、作成時間を確認するのは、 「それを PriorityBlockingQueue ex に入れる」のは間違った瞬間です:

thraed_1 は、ファイルの書き込みが完了するまで待たなければなりません。そして、それを「PriorityBlockingQueue ex :」に入れることができます。

ファイルへの書き込みが完了したことを検出するにはどうすればよいですか?

3 あまり複雑ではないオプション

  • a.) ファイルが作成され、ファイルの準備ができた時間を比較します。 また
  • b.) ファイルのサイズが着実に増加していることを確認します。ファイルが終了すると、成長が止まります。 また
  • c.) 一時フォルダーに移動してみてください。

あなたは何を好みますか?

私は解決策cを好むでしょう。

書き込み用に開かれたファイルは移動できません。サードパーティのプログラムがファイルを閉じた後、ファイルを移動できます。

必要な手順。

  • thread_1 は、サードパーティ プログラムによって作成されたファイルを監視しています。
  • thread_1 が xyztmp フォルダーに移動しようとしています (10 または 20 または ... 秒ごと)。
  • thread_1 は xyztmp フォルダーで新しい着信ファイルを探し、それを PriorityBlockingQueue ex に入れます。

解決策 b. はもっと複雑です。

thread_1 は、着信ファイル名とサイズを制御配列に入れて、3 ~ 5 回 (5 秒以上ごとに) 比較します。

配列

(filenamexyz.dat, size1, size2, size3, ...).
(filenameabc.dat, size1, size2, size3, ...).
(filenamefgh.dat, size1, size2, size3, ...).
....

5 つの比較サイズごとに名前で識別されるファイルが同じ場合、サードパーティ プログラムはこのファイルへの書き込みを完了しています。

これで PriorityBlockingQueue に入れることができます ex:

順を追って見ていきましょう

list.size が 2 のときに thread_2 が開始されたと仮定します。

  • サードパーティ プログラムがファイルを 1 つずつ書き込み始めます。
  • サードパーティ プログラムが FILE_1 の書き込みを開始します。
  • thread_1 は、作成された FILE_1 を検出し、リストに入れます。
  • サードパーティ プログラムが FILE_1 の書き込みを終了しました。
  • サードパーティ プログラムが FILE_2 の書き込みを開始します。
  • thread_1 は、作成された FILE_2 を検出し、リストに入れます。
  • if (priorityBlockingQueue.size) > 1) TRUE
  • thread_2 は、リスト FILE_1 の最初のファイルの読み取りと処理から開始します。

  • サードパーティ プログラムが FILE_2 の書き込みを終了しました。
  • サードパーティ プログラムが FILE_3 の書き込みを開始します。
  • thread_1 は、作成された FILE_3 を検出し、リストに入れます。
  • thread_2 が FILE_1 の処理を​​終了しました。
  • thread_2 は、リスト FILE_2 内の次のファイルから開始します。

  • サードパーティ プログラムが FILE_3 の書き込みを終了しました。
  • サードパーティ プログラムが FILE_4 の書き込みを開始します。
  • thread_1 は、作成された FILE_4 を検出し、リストに入れます。
  • thread_2 が FILE_2 の処理を​​終了しました。
  • thread_2 は、リスト FILE_3 内の次のファイルから開始します。

    今、トラブルが始まります


  • サードパーティ プログラムが FILE_4 の書き込みを終了しました。
  • サードパーティ プログラムが FILE_5 の書き込みを開始します。(FILE_5 は FILE_4 より大きい)。
  • thread_1 は、作成された FILE_5 を検出し、リストに入れます。
  • thread_2 が FILE_3 の処理を​​終了しました。
  • thread_2 は、リスト FILE_4 内の次のファイルから開始します。
  • thread_2 が FILE_4 の処理を​​終了しました。
  • thread_2 は、リスト FILE_5 内の次のファイルから開始します。
  • thread_2 は FILE_5 の処理を​​終了しました。
  • サードパーティ プログラムが FILE_5 の書き込みを終了しました。

サードパーティのプログラムが書き込むファイルが大きく、書き込みに時間がかかり、thread_2 が小さい FILE_4 の読み取りを終了した場合。

thread_2 は、ファイルが読み取り可能かどうかに関係なく、リストから次のファイル FILE_5 を取得します。

FILE_5 は、サードパーティ プログラムがまだ書き込みを行っているファイルです。FILE_5 は、thread_2 が読み取って処理しているファイルです。thread_2が読み取ったバイト数は、この時点でサードパーティ プログラムが書き込んだバイト数のみです。

于 2012-07-04T18:34:59.737 に答える