8

Javaでシングルトンパターンを実装するときに、この質問を思いつきました。以下にリストされている例は私の実際のコードではありませんが、元のコードと非常によく似ています。

public class ConnectionFactory{
    private static ConnectionFactory instance;

    public static synchronized ConnectionFactory getInstance(){
        if( instance == null ){
            instance = new ConnectionFactory();
        }

        return instance;
    }

    private ConnectionFactory(){
        // private constructor implementation
    }
}

静的同期メソッドの動作についてはよくわからないため、Google からいくつかの提案を得ています。同じクラスに複数の静的同期メソッドを持たない (またはできるだけ少なくする) ことです。静的同期メソッドを実装する場合、複数の静的同期メソッドがシステムのパフォーマンスを低下させる可能性があるため、クラス オブジェクトに属するロックが使用されると思います。

私は正しいですか?またはJVMは他のメカニズムを使用して静的同期メソッドを実装しますか? クラスに複数の静的同期メソッドを実装する必要がある場合のベスト プラクティスは何ですか?

皆さん、ありがとうございました!

敬具!

4

5 に答える 5

7

最善のアプローチ (コードの変更をできるだけ少なくする) は、次のようにすることです。

public class ConnectionFactory{
    private static ConnectionFactory instance = new ConnectionFactory();

    public static ConnectionFactory getInstance(){
        return instance;
    }

    private ConnectionFactory(){
    }
}

ご覧のとおり、getInstance今はメソッドが必要ないので、コードを次のように単純化できます。

public class ConnectionFactory{
    public static final ConnectionFactory INSTANCE = new ConnectionFactory();

    private ConnectionFactory(){
    }
}

同期に関する UPD: 最良の方法は、外部クラスからは見えないロックで同期することです。

public class ConnectionFactory{
    private static final Object lock = new Object();

    public static void doSmth() {
        synchronized (lock) {

           ...
        }
    }

    public static void doSmthElse() {
        synchronized (lock) {

           ...
        }
    }
}

this「なぜ同期が悪い考えなのか」については多くの議論がありますが(この例のように)、クラスの同期についても同じことが実際にあると思います。

于 2010-06-02T13:22:07.733 に答える
3

シングルトンを作成する方法はいくつかあります。

推奨される方法の1つは、列挙型を使用することです(1つのインスタンスのみを作成することが保証されています)。

public enum ConnectionFactory {

  INSTANCE;

}

または、クラスの読み込み時に静的に作成することもできます。

public class ConnectionFactory {

  private static ConnectionFactory INSTANCE = new ConnectionFactory();

  private ConnectionFactory() {}

  public static ConnectionFactory getInstance() {
    return INSTANCE;
  }    

}

遅延ロードする必要がある場合は、このイディオムを使用できます(二重チェックのロックアンチパターンではなく)

public class ConnectionFactory {

  private static class ConnectionFactoryHolder {
    private static ConnectionFactory INSTANCE = new ConnectionFactory();
  }

  public static ConnectionFactory getInstance() {
    return ConnectionFactoryHolder.INSTANCE;
  }

}
于 2010-06-02T13:27:01.340 に答える
2

はい、静的メソッドはクラス オブジェクトで同期されます。おそらくこれはパフォーマンスのホット スポットではないので、ここではパフォーマンスについて心配する必要はありません。シンプルに、いつでもどこでも最適化できます。

于 2010-06-02T13:22:09.467 に答える
2

静的同期メソッドは、クラスのロックを使用します。あなたの例の場合、 ConnectionFactory クラスオブジェクトのロックにアクセスしています。ベスト プラクティスは、ロックを必要以上に保持しないことです。複数の同期メソッドがあるかどうかは、それ自体は問題ではありません。

于 2010-06-02T13:22:24.003 に答える
0

有効な Javaでは、列挙型を使用してシングルトンを作成することをお勧めします。したがって、コードは次のようになります。

public enum ConnectionFactory{
INSTANCE;

// Other factory methods go here.

}

}

于 2010-07-01T19:49:59.270 に答える