web-dev-qa-db-ja.com

シングルトンパターン(Bill Pughのソリューション)

シングルトンパターンに関するウィキを読んでいますが、これを理解しているかどうかわかりません: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom 正しくその一部です。

簡単にするために:Bill Pughのソリューションが上記の例よりも優れているのはなぜですか?

静的クラスが実際に使用される前にVMなどによってロードされないため、getInstance()メソッドを使用する前にオブジェクトを作成しないためですか?そのメソッドは、オブジェクトを初期化する範囲でのみスレッドセーフですか?

31
Rob Fox

ピュー氏のバージョンは、getInstance()が呼び出されたとき、つまりクラス(getInstanceメソッドを保持するクラス)がロードされたときにのみシングルトンのインスタンス化を実行するため、高く評価されていると思います。あなたのシングルトン構造が何かをするなら高価それならこれはあなたにとって有利かもしれません。シングルトンが静的メソッドを回避するためだけのものである(そして依存性注入フレームワークに移行していない)世界の大多数のようであれば、私はそれで眠りを失うことはありません。

記事に記載されているように、Pugh氏のメソッドは静的インスタンス変数よりも遅延していますが、実際には、Singletonクラスが読み込まれると、とにかくgetInstanceメソッドを呼び出すことになります。したがって、コンピュータサイエンスの演習としては便利ですが、現実の世界ではその利点については議論の余地があります。

p.s.ここでのBloch氏の例では、列挙型を使用することはあまり気にしません。MySingletonIS-A列挙型は、私には正しく聞こえません(特に、インターフェイスを実装しないと言っている人からは)定数を取得します)

30
planetjones

JLSは、クラスが初めて使用されるときにのみロードされること(シングルトンの初期化を遅延させる)、およびクラスのロードがスレッド-であることを保証します。安全(getInstance()メソッドもスレッドセーフにします)

スレッドセーフな理由について

GetInstance()が初めて呼び出されるため、JVMはホルダークラスを保持します。別のスレッドがgetInstance()を同時に呼び出す場合、JVMはホルダークラスを2回ロードしません。最初のスレッドがクラスのロードを完了するのを待ち、ホルダークラスのロードと初期化の最後に両方のスレッドは、ホルダークラスが適切に初期化され、一意のシングルトンインスタンスを含むことを確認します。

23
JB Nizet

静的クラスが実際に使用される前にVM)によってロードされないためですか?

静的クラスだけでなく、あらゆるクラス。クラスは、参照されるまでロードされません。 JLSを参照してください- 12.4.1初期化が発生した場合

またはこのようなものなので、getInstance()メソッドに移る前にオブジェクトを作成しませんか?

丁度。

また、そのメソッドスレッドは、オブジェクトを初期化する範囲でのみ安全ですか?

参照の配布はスレッドセーフであるため、このメソッドは作成時だけでなく、常にスレッドセーフです。

7

静的クラスは、実際に使用される前にVMによって読み込まれないため、getInstance()メソッドを使用する前にオブジェクトを作成しないためですか?

正しい。

また、そのメソッドスレッドは、オブジェクトを初期化する範囲でのみ安全ですか?

これにより、インスタンスが1つだけ作成され、完全に初期化されたインスタンスへの参照以外はクライアントが受信しなくなります。

1

説明の重要な部分は次のとおりです。

ネストされたクラスは、getInstance()が呼び出された瞬間よりも早く参照されません(したがって、クラスローダーによって早くロードされません)。したがって、このソリューションは、特別な言語構造(つまり、揮発性または同期)を必要とせずにスレッドセーフです。

BillPoghのソリューションは怠惰を提供します。

1
khachik