インタビューは、多くの場合、この質問をした:だろうが、あなたはそれをシングルトン(Singletonパターンを)書いてください。まあ、書き込みへの書き込みは、これは容易ではありません。スムーズに書きます:
- 公共finalクラスEagerSingleton
- {
- プライベート静的EagerSingleton singObj =新しいEagerSingleton();
- プライベートEagerSingleton(){
- }
- パブリック静的EagerSingleton getSingleInstance(){
- singObjを返します。
- }
- }
いわゆる飢餓モードの文言は、使用の有無の各オブジェクトは初期化されています。これは、潜在的なパフォーマンス上の問題をもたらす可能性があります。オブジェクトが非常に高い場合は?このオブジェクトが使用されていない前に、それは巨大な廃棄物であることをメモリにロード置きます。遅延ロード(レイジーロードシングルトン) - このような状況に鑑み、我々は新しいデザインのアイデアを使用して、上記のコードに向上させることができます。
- 公共finalクラスLazySingleton
- {
- プライベート静的LazySingleton singObj = NULL;
- プライベートLazySingleton(){
- }
- パブリック静的LazySingleton getSingleInstance(){
- (ヌル== singObj)singObj LazySingleton =新しい()の場合。
- singObjを返します。
- }
- }
いわゆるレイジー・モードの文言。これは、初期化されていない、前にオブジェクトが使用されていないことを確認するために、遅延ロードを使用しています。一般的に、しかし、この時間は、新しいインタビュアーは、それのために物事を困難にするために質問をします。彼は尋ねます:文言のスレッドセーフ?答えはでなければなりません:安全。複数のスレッドがsingObj決定される9行目に同時に実行できるので、これは、次いで同時に初期化され、ヌルです。したがって、この問題は、このコードは、スレッドセーフであることを確認する方法はありますか?非常に単純な、プラスOKにそのメソッドの前に同期。
- 公共finalクラスThreadSafeSingleton
- {
- プライベート静的ThreadSafeSingleton singObj = NULL;
- プライベートThreadSafeSingleton(){
- }
- パブリック静的同期ThreadSafeSingleton getSingleInstance(){
- もし(ヌル== singObj)singObj ThreadSafeSingleton =新しいです();
- singObjを返します。
- }
- }
この書き込みパフォーマンス上の問題はありません:私は、インタビュアーはまだあなたを見て、物事を困難にしていき狡猾することができる、あなたに書くのか?答えは間違いなくイエスです!
価格は低下し、同時学位プログラムの同期のある程度にバインドされています
。、一方ではスレッドセーフであるためにどのような方法がありますが、同時実行も高度があるかもしれませんか?私たちは、その理由は、実際にはスレッドセーフではありませんことを、オブジェクトの初期化を、同期のサイズを小さくするオブジェクトが初期化されている場合にのみ同期するための方法を考えることが可能である場合に観察されます。ダブルチェックロッキング(ダブルチェックロック) -ここでは、新しいデザインのアイデアを提案する必要があります。
- 公共finalクラスDoubleCheckedSingleton
- {
- プライベート静的DoubleCheckedSingletonsingObj = NULL;
- プライベートDoubleCheckedSingleton(){
- }
- パブリック静的DoubleCheckedSingleton getSingleInstance(){
- IF(ヌル== singObj){
- 同期(DoubleCheckedSingleton.class){
- もし(ヌル== singObj)
- singObj =新しいDoubleCheckedSingleton();
- }
- }
- singObjを返します。
- }
- }
唯一の新しいロード・オブジェクトが完成ローディング後に同期されるように、文言は、他のスレッド内の9行目は、直接コードにロックスキップライン15のコストを決定することができます。同時性の非常に良好な程度を実行してください。
したがって、レイジー・ロードを達成する一方で上記の文言は、他にもすべてが完璧だった空想、同時実行スレッドセーフの良好な程度を行っています。これは、インタビュアーがあなたの答えに満足うなずきかもしれません、です。しかし、あなたはこの時点で行われ、実際には、このようなアプローチは依然として問題であると言います!!問題はどこにありますか?スレッドがライン9を実行するように想定され、オブジェクトが空であると判定され、その後、スレッドAは、オブジェクトを初期化するためにライン12に実行されるが、初期化には時間がかかり、実際にオブジェクトのアドレスがすでに存在しています。スレッドBはまた、9行目に、この時点で行われ、それは、このオブジェクトを取得するためにライン15に直接ジャンプする、空ではない判定されます。ただし、このオブジェクトがいる
完全に初期化されていません!
私が使用何完全に初期化されたオブジェクトを取得できませんでした!!ダブルチェックロックの議論の多くがありますが、それは今アンチパターンとして認識され、推奨されません!あなたのインタビュアーが、返信のこの声明を聞くときに、彼はそれを生きてホールドのではないでしょうか?
だから、どんな良いことが書かれてありますか?そこ!ここで再び新しいモデルを提案する - 。オンデマンドホルダーに初期化このメソッドは、この内部クラスの初期化時に、JLS(Java言語Sepcification)は、このクラスのスレッドセーフなことを保証します、遅延読み込みオブジェクトを行うために内部クラスを使用しています。最大の美の文言は、Java仮想マシンのメカニズムの完全な使用は保証ではなく、synchronizedキーワードを同期することです。
- パブリッククラスシングルトン
- {
- プライベート静的クラスSingletonHolder
- {
- 公共最終静的シングルトンインスタンス=新しいシングルトン()。
- }
- パブリック静的シングルトンのgetInstance()
- {
- SingletonHolder.instanceを返します。
- }
- }
この時点で、それが終了しました。あなたの参考のためにリンクを提供します:
デマンドホルダー上Initialzation:
http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom