2

2 つ (またはそれ以上) の同時実行 Java プロセスがファイルの存在を確認し、存在しない場合は作成し、実行中にそのファイルから読み取る必要があるとします。複数のライター プロセスが相互に上書きしたり、リーダー プロセスがファイルの不完全または一貫性のないバージョンを読み取ったりする可能性から身を守りたいと考えています。

この状況を調停するために現在行っていることは、Java NIO FileLocks を使用することです。1 つのプロセスは、作成するファイルの排他ロックを取得して作成しますがFileChannel.tryLock()、同時に実行されている他のプロセスはロックを取得できず、ファイルのメモリ内バージョンを使用して実行するようにフォールバックします。

ただし、ロックはコンピューティング ファームでさまざまな問題を引き起こしているため、代替手段を検討しています。私の質問は次のとおりです。ファイルロックを使用せずにこれを安全に行う方法はありますか?

たとえば、ファイルが存在しないことがわかったときにプロセスが独立した一時ファイルに書き込み、書き込み後に一時ファイルを多かれ少なかれ「アトミックに」移動することはできますか? このシナリオでは、最終的に複数の書き込みプロセスが発生する可能性がありますが、ファイルから読み取るプロセスが常にいずれかのバージョンを読み取り、2 つ以上のバージョンが混在していない場合は問題ありません。ただし、読み取り用にファイルを開いている場合、読み取りの途中で上書きされたとしても、元のバージョンのファイルから引き続き読み取りを行うことがすべてのオペレーティング システムで保証されているわけではありません。

どんな提案でも大歓迎です!

4

1 に答える 1

2

2 つ (またはそれ以上) の同時実行 Java プロセスが、ファイルの存在を確認し、存在しない場合は作成し、実行中にそのファイルから読み取る必要があるとします。

質問の作成と読み取りの部分がよくわかりません。一意のファイルがあることを確認したい場合は、 を使用new File(...).createNewFile()して、それが返されることを確認できますtrue。Javadocs から引用するには:

この名前のファイルがまだ存在しない場合にのみ、この抽象パス名で指定された新しい空のファイルを原子的に作成します。ファイルが存在するかどうかのチェックと、存在しない場合のファイルの作成は、ファイルに影響を与える可能性のある他のすべてのファイルシステム アクティビティに関してアトミックな単一の操作です。

これにより、そのプロセス(またはスレッド)のみが「所有」する一意のファイルが得られます。ただし、どのファイルに書き込むかをライターに知らせる方法を計画していたかどうかはわかりません。

あなたが書いた一意のファイルを作成し、書き込みディレクトリに移動して消費することについて話している場合は上記が機能するはずです。同様に完了したら、書き込みディレクトリに一意の名前を作成する必要があります。

次のようなものを使用できます。

private File getUniqueFile(File dir, String prefix) {
    long suffix = System.currentTimeMillis();
    while (true) {
        File file = new File(dir, prefix + suffix);
        // try creating this file, if true then it is unique
        if (file.createNewFile()) {
           return file;
        }
        // someone already has that suffix so ++ and try again
        suffix++;
    }
}

UUID.randomUUID()別の方法として、または何かを使用して一意のファイル名を作成し、一意の名前を生成することもできます。

于 2013-04-16T20:09:19.270 に答える