3

それ自体の他のインスタンスを検出して実行を防止できるアプリケーションを作成したいと考えています。これを達成するために、アプリケーション固有のポートで新しいポートを開きServerSocket、同じポートに複数回バインドしようとするとスローされる例外に依存して、重複するアプリケーションを「検出」して強制終了することを考えています。インスタンス。現在の作業ディレクトリにファイルを書き込み、それを「検出」して同じ種類の動作を実現できることは知っていますが、実際にはこれを実行したくありません (アプリが停止して実行できない場合に何が起こるか)。ファイルを削除しませんか?)、それがServerSocketルートを選択した理由です。

次のコードがあるとします。

public class MyClass{
    public static void main(String[] args) throws IOException{
        new ServerSocket(1234);

        new Thread(){
            //This is a non-daemon thread. Assume its run() method never returns.
        }.start();
    }
}

質問

を作成するServerSocket以外は、アプリケーションで再度使用する必要はまったくありません。その存在だけで、アプリの別のインスタンスが起動を試みたことを検出できるからです。したがって、上への参照を保存するとServerSocket、コンパイル警告 (未使用の参照) が発生します。私はきちんとしたフリークなので、避けられるのであれば参照を保存したくありません。私の質問は、このServerSocketインスタンスは、すべての非デーモン スレッドが終了する前にガベージ コレクションを取得しますか (アプリが失敗したり、他の方法で終了したりしないと仮定します)。

4

2 に答える 2

4

私は混乱しています。あなたは「きちんとしたフリーク」ですが、通常の終了の場合にアプリケーションの制御下でクローズ手順を実行するよりも、ガベージコレクターの気まぐれにソケットをクローズしたままにしますか? (そのようなメカニズムを配置するには、参照を保持する必要があり、認識されている問題を排除するため、これが当てはまると思います。)

参考までに、参照を保持しなくても実際に問題が発生することはないと思います。

  • 内部的には、ソケットがバインドされている間、参照が保持される可能性があります
  • ServerSocket の close() メソッドがガベージ コレクションで呼び出される可能性があります。AbstractPlainSocketImpl の finalize() メソッド内で呼び出されるため、原則として が呼び出されますが、実際に finalize メソッドが呼び出される保証はありません。
  • アプリケーションが異常終了した場合、ソケットがすぐにバインド解除されるという保証はありませんが、最近の O/Ses ではそうなる可能性があります (これをテストするのが最善です)。

ただし、アプリが正常にシャットダウンされる場合に備えて、「クリーン」なシャットダウン メカニズムをコーディングすることを強くお勧めします。そのためには、ソケットへの参照を保持する必要があります。したがって、代わりに賢明なプログラミングの実践を使用するだけであれば、存在する必要のない問題を実際に自分で発明していると思います。

于 2012-05-22T00:19:15.910 に答える
1

さて、以前の間違った理解から自分自身を贖うことを試みましょう。あなたが言及するファイルロックとソケットのテクニックは広く使われていますが、別のテクニックがあります-yorプログラムの現在のインスタンスを(メソッドregisterとderegisterを介して)保持するオブザーバーを持っています。

別のインスタンスが実行されているときに新しいインスタンスを登録しようとすると、登録プロセスが失敗し、アプリケーションが正常に終了する可能性があります。

次に、アプリケーションは、アプリケーションがまだ稼働していることをオブザーバーが認識できるように、beObservedメソッドを1つ含むインターフェースObservableを実装できます。したがって、アプリケーションがクラッシュすると、定期的なチェックが失敗し、クラッシュしたアプリケーションの登録が自動的に解除されます。

于 2012-05-22T12:05:12.143 に答える