15

特定の時間に実行できる Java プログラムのインスタンスは 1 つだけである必要があります。以前のさまざまな投稿で、スタック オーバーフローで提案された多数のソリューションを確認しました。

ソリューションは以下に基づいています。

  • ソケットを開く: ソケット接続を開きます。
  • ファイルのロックに基づく: 一時ファイルを作成し、ロックを保持します。また、シャットダウン フックを追加して、JVM のシャットダウン時にそのファイルのロックを解除します。

ポートの使用で競合が発生する可能性があるため、ポート ロックは使用したくありません。

そこで、ファイルロックを使用することを考えていました。少し調べたところ、ポート ロック ベースのメカニズムの支持者は、アプリケーションがクラッシュした場合やその他の IO エラーが発生した場合、ファイル ロックが信頼できない可能性があると述べていることがわかりました。

私が必要としているのは、クロス プラットフォームおよび複数の JDK で一貫して機能するソリューションを見つけることです。私が意図するプラットフォームは Windows と Linux であり、JDK は Sun と IBM JDK です。

誰でもこれに光を当てることができますか?

4

5 に答える 5

6

Unix システムでよく行われる方法は、アトミック操作であるファイルを作成し、ファイルを作成できるかどうかを確認することです。ファイルを作成できた場合、そのプロセスはロックされており、実行が許可されています。ファイルを作成できなかった場合は、他の誰かがロックを取得している必要があり、インスタンスはすぐに終了します。そのようなことのためのコード

private boolean lock()
 {
   try
    {
        final File file=new File("bpmdj.lock");
        if (file.createNewFile())
        {
            file.deleteOnExit();
            return true;
        }
        return false;
    }
    catch (IOException e)
    {
        return false;
    }
}

アプリのメインで、次に始めます

    if (!lock())
    {
        System.out.println("Cannot lock database. Check that no other instance of BpmDj is running and if so, delete the file bpmdj.lock");
        return;
    }

もちろん、注意すべき点が 2 つあります。まず第一に、アプリが激しくクラッシュした場合、ファイルが削除されない可能性が非常に高く、ユーザーに不便をもたらします (ロックファイルを自分で削除する必要があります)。

第二に、Javaのドキュメントには次のように記載されています。

createNewFileこの名前のファイルがまだ存在しない場合にのみ、新しい空のファイルをアトミックに作成します。ファイルが存在するかどうかのチェックと、存在しない場合のファイルの作成は、ファイルに影響を与える可能性のある他のすべてのファイルシステム アクティビティに関してアトミックな単一の操作です。注: この方法はファイルのロックには使用しないでください。結果として得られるプロトコルを確実に機能させることはできません。代わりに FileLock 機能を使用する必要があります。

特に最後のメモは興味深いものです。なぜなら、この場合、ファイルのロックには実際には使用せず、同じアプリケーションの他のインスタンスが存在しないことを確認するためだけに使用するからです。それでも、「結果のプロトコルを信頼できるように動作させることはできない」と彼らが書いている理由を理解するのは少し興味があります

于 2014-12-04T14:54:08.480 に答える
1

C に精通している場合は、Windows の名前付きパイプと UNIX のローカル ソケットでこの問題に対処できます。どちらも JNI が少し必要です。これらの通信チャネルはアプリケーションのリソースであるため、アプリケーションがクラッシュした場合、OS はリソースを解放する義務があります。さらに、それらはテキスト名で識別されるため、名前が衝突する可能性はファイル ロックの場合と同じです。

このstackoverflow answerでローカルソケットの例をピックアップできます。

Windows での名前付きパイプの例は、ここにあります。

于 2013-09-29T19:45:35.840 に答える
0

JUnique ライブラリを使用できます。単一インスタンスの Java アプリケーションの実行をサポートし、オープンソースです。これはファイル ロックに基づいていますが、ランダム ポートを使用して、実行中の他の Java インスタンスからメッセージを送受信します。

http://www.sauronsoftware.it/projects/junique/

How to implement a single instance Java application?での私の完全な回答も参照してください。

于 2016-11-23T11:38:05.333 に答える