140

静的コード ブロックを使用して、レジストリ内の一部のコントローラーを初期化しています。したがって、私の質問は、クラスが最初にロードされたときに、この静的コード ブロックが絶対に 1 回だけ呼び出されることを保証できますか? このコード ブロックがいつ呼び出されるかを保証できないことは理解しています。クラスローダーが最初にロードしたときだと思います。静的コード ブロック内のクラスで同期できることはわかっていますが、これは実際に起こることなのでしょうか?

簡単なコード例は次のとおりです。

class FooRegistry {

    static {
        //this code must only ever be called once 
        addController(new FooControllerImpl());
    }

    private static void addController(IFooController controller) { 
        // ...
    }
}

または、これを行う必要があります。

class FooRegistry {

    static {
        synchronized(FooRegistry.class) {
            addController(new FooControllerImpl());
        }
    }

    private static void addController(IFooController controller) {
        // ...
    }
}
4

6 に答える 6

203

はい、Java 静的初期化子はスレッドセーフです (最初のオプションを使用してください)。

ただし、コードが 1 回だけ実行されるようにしたい場合は、クラスが単一のクラスローダーによってのみロードされるようにする必要があります。静的初期化は、クラスローダーごとに 1 回実行されます。

于 2009-05-18T16:43:44.947 に答える
13

これは、遅延初期化に使用できるトリックです

enum Singleton {
    INSTANCE;
}

またはJava 5.0より前の場合

class Singleton {
   static class SingletonHolder {
      static final Singleton INSTANCE = new Singleton();
   }
   public static Singleton instance() {
      return SingletonHolder.INSTANCE;
   }
}

SingletonHolder の静的ブロックはスレッド セーフな方法で 1 回実行されるため、他のロックは必要ありません。クラス SingletonHolder は、 instance() を呼び出したときにのみロードされます

于 2009-05-18T18:57:24.770 に答える
4

通常の状況では、静的初期化子のすべてがそのクラスを使用するすべての前に発生するため、通常、同期は必要ありません。ただし、このクラスは、静的初期化子が呼び出すすべてのものにアクセスできます (他の静的初期化子を呼び出すことを含む)。

クラスは、ロードされたクラスによってロードできますが、必ずしもすぐに初期化されるとは限りません。もちろん、クラスはクラスローダーの複数のインスタンスによってロードされるため、同じ名前の複数のクラスになる可能性があります。

于 2009-05-18T16:44:44.070 に答える
3

はい、ちょっと

イニシャライザは1回しか呼び出されないため、その定義ではスレッド セーフです。スレッドの競合を発生させるstaticには、イニシャライザを 2 回以上呼び出す必要があります。static

とはいえ、static初期化子は他の多くの点で混乱を招きます。それらが呼び出される特定の順序は実際にはありません。staticイニシャライザが相互に依存する2 つのクラスがある場合、これは非常に混乱します。staticまた、クラスを使用してもイニシャライザが設定するものを使用しない場合、クラス ローダーが静的イニシャライザを呼び出すとは限りません。

最後に、同期しているオブジェクトに注意してください。これは実際にはあなたが求めていることではないことは理解していますが、あなたの質問がaddController()スレッドセーフにする必要があるかどうかを実際に尋ねていないことを確認してください.

于 2009-05-18T16:50:59.707 に答える
0

はい、静的初期化子は 1 回だけ実行されます。 詳細については、こちらをお読みください

于 2009-05-18T16:49:53.467 に答える
-4

したがって、基本的には、シングルトン インスタンスが必要なため、多かれ少なかれ昔ながらの方法で行い、シングルトン オブジェクトが一度だけ初期化されるようにする必要があります。

于 2015-05-12T22:16:41.990 に答える