何が効率的な方法で実施するシングルトンパターンのJava?[定休日]

StackOverflow https://stackoverflow.com/questions/70689

  •  09-06-2019
  •  | 
  •  

質問

何が効率的な方法で実施するシングルトンパターンのJava?

役に立ちましたか?

解決

利用の列挙型:

public enum Foo {
    INSTANCE;
}

ジョシュア-ブロッホの説明このアプローチ人 効果的なJavaのリローデッド にて講演Google I/O2008年 リンクビデオ.もスライドとの関係30-32プレゼンテーションの(effective_java_reloaded.pdf):

グ方法、上達するためのコツなどを直列化可能でないシングルトン

public enum Elvis {
    INSTANCE;
    private final String[] favoriteSongs =
        { "Hound Dog", "Heartbreak Hotel" };
    public void printFavorites() {
        System.out.println(Arrays.toString(favoriteSongs));
    }
}

編集: An オンラインの一部を"有効"Java" "と言ってい

"このアプローチは機能的に同等の公共分野のアプローチされないことを除いてより簡潔に、直列化機械を無料で提供鉄に対する性能を保証する複数のインスタンス化のるつもりだったので洗練された直列化または反射ます。このアプローチが広く採用され、 単一の要素の列挙型が最良の方法を実施するsingleton."

他のヒント

用途によっては、複数の"正しい"答えなのです。

以来、java5に最善の方法を使用するためには、enum:

public enum Foo {
   INSTANCE;
}

前java5、最も単純な例です:

public final class Foo {

    private static final Foo INSTANCE = new Foo();

    private Foo() {
        if (INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return INSTANCE;
    }

    public Object clone() throws CloneNotSupportedException{
        throw new CloneNotSupportedException("Cannot clone instance of this class");
    }
}

うにコードです。まず、希望のクラスが認めた場合はこの限りでない。この場合に使用しましたの final キーワードは、ユーザーには知って最終とする。する必要があり、コンストラクタ、リニューアルグランドオープはユーザーをFoo.例外をスローからのコンストラクタユーザーの利用への反映を目Foo.そして自分の好きな名前を付けて private static final Foo 分野のみインスタンス、 public static Foo getInstance() 方法を返します。Javaの仕様のコンストラクタが呼び出されるのは、クラスが最初に使用します。

ときもオブジェクト、重建コードや他のアクセスのstaticメソッドまたは分野で使用される前にインスタンスを必要としなければいけないのですが、利用する必要があり怠け者を設定する処理です。

ご利用でき private static class への負荷のインスタンス.のコードが次のように見え:

public final class Foo {

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }
}

以来、ライン private static final Foo INSTANCE = new Foo(); はだけた場合に実行されるクラスFooLoaderは、実際に使いこなどを中心に、lazyインスタンス生成がで保証するスレッドで安全です。

きものにしたいと望んでいserialize御オブジェクトに必要なものだと直列化復元さんをコピーします。

public final class Foo implements Serializable {

    private static final long serialVersionUID = 1L;

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }

    @SuppressWarnings("unused")
    private Foo readResolve() {
        return FooLoader.INSTANCE;
    }
}

の方法 readResolve() してのみインスタンスが返された場合でも、オブジェクトに連載された以前の実行います。

免責事項: いくとすべての答えを書いたので私の言葉です。


実践によるシングルトン2つのオプション
1.Lazy荷
2.早期負荷

怠け者の負荷を追加しビットのオーバーヘッドの正直で使用することができるもの非常に大きなオブジェクト、重建コードや他のアクセスのstaticメソッドまたは分野で使用される前にインスタンスを必要としなければいけないのですが、利用する必要があり怠け者を設定する処理です。その他を選択早積られます。

プリケーションの実現にはシングルトンは

public class Foo {

    // It will be our sole hero
    private static final Foo INSTANCE = new Foo();

    private Foo() {
        if (INSTANCE != null) {
            // SHOUT
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return INSTANCE;
    }
}

すべてが良いのを除き、その初期のロシングルトン.きみlazyロードシングルトン

class Foo {

    // Our now_null_but_going_to_be sole hero 
    private static Foo INSTANCE = null;

    private Foo() {
        if (INSTANCE != null) {
            // SHOUT  
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        // Creating only  when required.
        if (INSTANCE == null) {
            INSTANCE = new Foo();
        }
        return INSTANCE;
    }
}

これまでにないもののヒーローのままでは存続不可能になっていながら戦うだけで複数のスレッドが悪い多くのインスタンスのヒーローがあります。では、その保護を魔除けのマルチスレッド

class Foo {

    private static Foo INSTANCE = null;

    // TODO Add private shouting constructor

    public static Foo getInstance() {
        // No more tension of threads
        synchronized (Foo.class) {
            if (INSTANCE == null) {
                INSTANCE = new Foo();
            }
        }
        return INSTANCE;
    }
}

しかし、これでは不十分での保護を行主人公、本当だって!!このまで可能かヒーロー

class Foo {

    // Pay attention to volatile
    private static volatile Foo INSTANCE = null;

    // TODO Add private shouting constructor

    public static Foo getInstance() {
        if (INSTANCE == null) { // Check 1
            synchronized (Foo.class) {
                if (INSTANCE == null) { // Check 2
                    INSTANCE = new Foo();
                }
            }
        }
        return INSTANCE;
    }
}

これを"ダブルチェックロックム".で忘れては揮発性の声で分かりにくいが必要です。
詳しくは: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

いい悪のスレッドがどの残虐な直列化?していながらも、デserialiaztion新しいオブジェクトの作成

class Foo implements Serializable {

    private static final long serialVersionUID = 1L;

    private static volatile Foo INSTANCE = null;

    // Rest of the things are same as above

    // No more fear of serialization
    @SuppressWarnings("unused")
    private Object readResolve() {
        return INSTANCE;
    }
}

の方法 readResolve() してのみインスタンスが返された場合でも、オブジェクトに連載された以前の実行のプログラム。

最後に今までに十分に対する保護のスレッドは、直列化が当社のコードでの段階での醜い.きちヒーローを作る

public final class Foo implements Serializable {

    private static final long serialVersionUID = 1L;

    // Wrapped in a inner static class so that loaded only when required
    private static class FooLoader {

        // And no more fear of threads
        private static final Foo INSTANCE = new Foo();
    }

    // TODO add private shouting construcor

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }

    // Damn you serialization
    @SuppressWarnings("unused")
    private Foo readResolve() {
        return FooLoader.INSTANCE;
    }
}

それでは当社も同じ主人公:)
以来、ライン private static final Foo INSTANCE = new Foo(); はだけた場合に実行されるクラス FooLoader 実際にそれを使いこなどを中心に、lazyインスタンス生成,

とがで保証するスレッドで安全です。

またこれまでに、こちらを実現する最善の方法は、あなたまたはこの高級

 public enum Foo {
       INSTANCE;
   }

る内部で使う

public class Foo {

    // It will be our sole hero
    private static final Foo INSTANCE = new Foo();
}

るのではないのです。恐れの直列化、スレッドは、醜います。も ENUMSシングルトンには遅延初期化され.

このアプローチは機能的に同等の公共分野のアプローチ ことをより簡潔に、直列化機械 無料で、鉄に対する性能を保証する複数の インスタンス化のるつもりだったので洗練された直列化または 反射。このアプローチが広く採用され、 単一の要素の列挙型が最良の方法を実施するsingleton.

-ジョシュア-ブロッホの"効果的なJava"

現場を実現していなぜENUMSなどを実施シングルトンを増しばらくお待ちくだ:)
更新することができ ブログ.

の溶液を投稿したStuトンプソンが有効なJava5.0以降である。だが私はあまり好きではないので使うのだと思うから誤りに陥りやすい。

で忘れては揮発性の声で分かりにくいが必要です。なの揮発性このコードはスレッドに対して安全なによりのダブルチェックロックantipattern.詳しくはこの項16.2.4の Java並行処理で実際に.短:このパターン(以前のJava5.0またはずの揮発性計算書)への参照を返します、バーのオブジェクトは(まだ)に誤りがあった。

このパターンで発明された性能を最適化するこんな不ます。以下のぐさの初期化コードが速く、より重要なのは-読みやすくなりました。

class Bar {
    private static class BarHolder {
        public static Bar bar = new Bar();
    }

    public static Bar getBar() {
        return BarHolder.bar;
    }
}

スレッドに対して安全にJava5+:

class Foo {
    private static volatile Bar bar = null;
    public static Bar getBar() {
        if (bar == null) {
            synchronized(Foo.class) {
                if (bar == null)
                    bar = new Bar(); 
            }
        }
        return bar;
    }
}

編集:に注意を払う volatile 修飾子です。:)ことが重要ではないので、他のスレッドを保証するものではありませんのJMM(Javaメモリモデルへの変化に値する。同期 ない のことでのみ列化へのアクセスをブロックします。

編集2:@Bno"の回答内容のアプローチが推奨する法案ピュー(FindBugs)とは議論の余地。行きを読み、議で自分の答えます。

忘れられ 怠け者の初期化, でも問題がある。これは、最も単純な解

public class A {    

    private static final A INSTANCE = new A();

    private A() {}

    public static A getInstance() {
        return INSTANCE;
    }
}

してくださいする必要があります。うgoogleのために"シングルトン抗パターン"を議論する技術を開発しているのですにある本質的に違うと思うな機構をもグローバル-リソース/データなので、信頼性の向上に努めていますが最高です。特に私がその場で発音を確認することが依存性注射用中の場合も利用ユニットテストでジで利用できる英資源のための試験。

私mystifiedに答えることを示唆するものもみられるジの代替として使用singletons;これらの関係のな概念です。利用できるDI注入のいずれか単独またはnon-シングルトン(例:スレッド)インスタンス.少なくともこれがtrueの場合にご使用の2.x,ったその他のジの枠組み

私の回答のOPする(すべてのもの些細なサンプルコード):

  1. 使用DI枠組みのような春、そして
  2. でのディの構成かどうかの依存関係はsingletons請scoped、セッションscopedなどを実行します。

このアプローチするこのホ互いに分離(およびそのため柔軟なテスト)アーキテクチャを使用するかどうかシングルトンは容易に可逆的な実装の詳細(提供してくsingletonsまthreadsafeますか?

本当に考えるのはなぜ必要なシングルトンから書き込みます。あ準宗教についての議論用できる非常に簡単につまずくだgoogle singletons Java.

個人としてはしないようにしてsingletonsしていくことができ多くの理由のものであることにご留意くださgoogling singletons.感じることもしばしばsingletonsは虐待を受けなが理解しやすいように、彼らは使用する仕組みとしての"グローバル"へのデータOOデザインに使用されていな事態を回避するためにオブジェクトライフサイクルマネジメント(または本当に考えることができなからB)。う逆転の制御(IoC)には依存関係を噴射(DI)のための素敵なmiddleground.

まる必要がありそのwikipediaには良い例の適正な実施のシングルトン.

以下の3つの異なるアプローチ

1)Enum

/**
* Singleton pattern example using Java Enumj
*/
public enum EasySingleton{
    INSTANCE;
}

2)ダブルクロック/Lazy荷

/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
     private static volatile DoubleCheckedLockingSingleton INSTANCE;

     private DoubleCheckedLockingSingleton(){}

     public static DoubleCheckedLockingSingleton getInstance(){
         if(INSTANCE == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                //double checking Singleton instance
                if(INSTANCE == null){
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
         }
         return INSTANCE;
     }
}

3)Staticファクトリメソッド

/**
* Singleton pattern example with static factory method
*/

public class Singleton{
    //initailzed during class loading
    private static final Singleton INSTANCE = new Singleton();

    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}

私はSpring Frameworkを使管理もsingletons.な執行の"シングルトンらしさ"のクラスをしたりすることはできませんいかが複数ある場合はクラスローダに終えることができました。を前提としますが、本当に簡単に構築することが可能となる、設定の異なる工場作成の異なる種類のオブジェクト。

バージョン1:

public class MySingleton {
    private static MySingleton instance = null;
    private MySingleton() {}
    public static synchronized MySingleton getInstance() {
        if(instance == null) {
            instance = new MySingleton();
        }
        return instance;
    }
}

怠け者の負荷、スレッドに対して安全にブロッキング、低性能が synchronized.

バージョン2:

public class MySingleton {
    private MySingleton() {}
    private static class MySingletonHolder {
        public final static MySingleton instance = new MySingleton();
    }
    public static MySingleton getInstance() {
        return MySingletonHolder.instance;
    }
}

怠け者の負荷、スレッドに対して安全に非ブロッキング、高性能。

Wikipediaには のsingletons、Java.Javaの5実施に見え、レ(ダブルチェックをロックます。

しない場合には流を積載しない

public class Singleton {
    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() { return Singleton.INSTANCE; }

    protected Object clone() {
        throw new CloneNotSupportedException();
    }
}

したい場合はlazy荷び出すためのものではありませんでおりますスレッドを安全にダブルチェックパターン

public class Singleton {
        private static Singleton instance = null;

        private Singleton() {}

        public static Singleton getInstance() { 
              if(null == instance) {
                  synchronized(Singleton.class) {
                      if(null == instance) {
                          instance = new Singleton();
                      }
                  }
               }
               return instance;
        }

        protected Object clone() {
            throw new CloneNotSupportedException();
        }
}

としてのダブルチェックパターンを保証するものではありませんの仕事よりも問題コンパイラでコンパイルわかんないものである、ということについての質問です。), きもののみを同期させるために全体のgetInstance法を登録するすべてのものSingletons.

私の言うとおりのEnumシングルトン

シングルトンのenumを用いたJavaにおける一般的方法を宣言するのに列挙型シングルトン.Enum singletonインスタンス変数を含む場合があり、インスタンス方法。簡単のため、また、ご利用の場合は他のインスタンスメソッド以上を確保する必要がありスレッドの安全性はそのメソッドの場合が多いです。に影響する状態でオブジェクトです。

の利用の列挙型が容易なため、欠点に関して直列化可能オブジェクトを回避をすることはいたしません。

/**
* Singleton pattern example using Java Enum
*/
public enum Singleton {
        INSTANCE;
        public void execute (String arg) {
                //perform operation here
        }
}

アクセスできるよ Singleton.INSTANCE, 以前に比べて簡単になりより呼び出し getInstance() 法Singleton.

1.12直列化のEnum定数

Enum定数の直列化されたとは違った通常の直列化可能または外部化可能オブジェクト。直列化された形で含まれるenum定数のみで構成されていますの名前フィールド値は一定の形式です。にserialize enum定数 ObjectOutputStream 書き込みによって返された値に含まれるenum定数の名前。を直列化復元の列挙型定数、 ObjectInputStream を読み込み定数の名前からストリームの直列化復元の定数はそれぞれの呼び出しによる java.lang.Enum.valueOf 法の定数のenum型に受け取った定数名として論争することができます。のような他の直列化可能または外部化可能オブジェ、enum定数のターゲットとして機能の参考文献に現れるその後の直列化ストリームです。

そのプロセスのenum定数を直列化できないカスタマイズ:クラス特有の writeObject, readObject, readObjectNoData, writeReplace, は、 readResolve 法に定義されたenum型は無視され中の直列化と直列化復元.同様に、 serialPersistentFields または serialVersionUID 分野の宣言も無視され--すべてのenum型に固定 serialVersionUID0L.記録の直列化可能領域のデータのためのenum型が不要なものがないため、変化するタイプのデータ送信されます。

引用Oracle docs

その他の問題は、従来のSingletonsていることを実装する Serializable インターフェイスのできない状態でシングルトン readObject() メソッドは常に新しいインスタンスを返しのようにコンストラクタは、Java.これを使う事により、避ける事ができ readResolve() ね新しく作成されたインスタンスに置き換えとのシングルトン以下のように

 // readResolve to prevent another instance of Singleton
 private Object readResolve(){
     return INSTANCE;
 }

することができるのはなぜなのでより複雑な場合はシングルトンクラスの維持の状態で、お客様のご要望に応じてその過渡的なものに列挙型シングルトン、直列化を保証するJVM.


よく読

  1. シングルトンパターン
  2. Enums,Singletonsおよび直列化復元
  3. ダブルチェックロックとのシングルトンパターン

が少し遅めのゲームのことが多いニュアンスが周辺を実施シングルトン.ホルダーパターンは使用できませんでくる。およびIMO利用の場合、揮発性のも使用地域の変数となります。まず初めに、繰り返し処理を実行し、問題です。だかっていうのかな。


初の試みとなるようになります:

public class MySingleton {

     private static MySingleton INSTANCE;

     public static MySingleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new MySingleton();
        }

        return INSTANCE;
    }
    ...
}

このMySingletonクラスは、民間の静的バランスタンスは、staticメソッドを呼getInstance().初めてgetInstance()が呼ばれるインスタンス委員はnullになります。その流れにその作成条件として新しいインスタンスを作成し、MySingletonクラスです。それ以降の呼び出しにgetInstance()のインスタンス変数を設定していないもうひとつ作成しMySingletonインスタンス.これにより、あのインスタンスMySingletonが共有すべての呼び出し側のgetInstance().

この実装に問題です。マルチスレッド用してレース状態の創設に関する単一のインスタンス.複数のスレッドの実行のgetInstance()メソッドでは周辺)同時に、彼らはそれぞれのインスタンスの会員としてnullになります。この結果は各スレッドを新規作成MySingletonインスタンスとその後の設定インスタンス。


private static MySingleton INSTANCE;

public static synchronized MySingleton getInstance() {
    if (INSTANCE == null) {
        INSTANCE = new MySingleton();
    }

    return INSTANCE;
}

ここで使用していますので同期をキーワードは、メソッドシグニチャーを同期させるためにgetInstance()メソッドがあります。これは確実に固定してレースの条件です。スレッドは現在のブロック入力の方法です。いものを作成し、性能の問題です。この実装は同期化させる創造の単一インスタンスで同期すべての通話をgetInstance()を含むります。を読み込みする必要のない同期していない値を返しのインスタンス.以降を読み込みもあるかもしれませんが、バルクの電話(このインスタンス生成のみが最初の呼び出しが発生する不要なパフォーマンスとの同期により、全体の方法です。


private static MySingleton INSTANCE;

public static MySingleton getInstance() {
    if (INSTANCE == null) {
        synchronize(MySingleton.class) {
            INSTANCE = new MySingleton();
        }
    }

    return INSTANCE;
}

この移動同期の方法に署名、同期ブロックのロッドやルアーを使用することはMySingletonインスタンス.では本題を解決する問題なのか。していないブロックに読み込みの際には、きちんとされてき戻してしまった。複数のスレッドのgetInstance()メソッドでは同時期にすべてのインスタンスの会員としてnullになります。その場合は、それに同期ブロックが取得、ロスエロエスデイキケ記のインスタンス.このスレッドから抜け出すブロック、他のスレッドの可愛のロックは、一つ一つ各スレッドが下落を通じて、マテリアルリサイクルの作成新しいインスタンスのクラスです。なので、来客の多い企業にはお返します。


private static MySingleton INSTANCE;

public static MySingleton getInstance() {
    if (INSTANCE == null) {
        synchronized(MySingleton.class) {
            if (INSTANCE == null) {
                INSTANCE = createInstance();
            }
        }
    }

    return INSTANCE;
}

この問題は別のチェックの中からブロックです。場合は、インスタンスの会員が設定されていまskipを設定する処理です。これをダブルチェックロックしなければなりません。

この解決問題の複数のスインスタンスで、弊社のソリューションして表示して他の課題です。その他のスレッドがない"見る"のインスタンス委員を更新しました。このJavaメモリを最適化。スレッドのコピーには元の値を変数からメインメモリ、CPUます。変数に書き込まれ、から読み取れます。この特徴であるJavaが最適化されるように設計されます。がこの問題のための当社のシングルトンの実装です。第二のスレッド処理により異なるCPUやコアを用い、異なるキャッシュするとは考えないかもしれない化されたコードを生成するために初めてとなります。このスレッドのインスタンスの会員としてnullにない新しいインスタンスのシングルトンを作成します。


private static volatile MySingleton INSTANCE;

public static MySingleton getInstance() {
    if (INSTANCE == null) {
        synchronized(MySingleton.class) {
            if (INSTANCE == null) {
                INSTANCE = createInstance();
            }
        }
    }

    return INSTANCE;
}

解決し、この揮発性キーワードの宣言のインスタンス。このコンパイラを常時からの読み込み、書き込みを行うメインメモリ、CPUます。

この簡単な変更によるものであり、コスト。もたらされず、CPUキャッシュ、私たちはパフォーマンスし、揮発性のインスタンス委員—グローバルで選ばれる4。まダブルチェックの存在(1、2)、値を設定する(3)その値を返します(4).一つだと言えるのはこのパスは、縁取りの場合としてのインスタンスの最初の呼び出しの方法です。にこのようなパフォーマンスを作らはまずまずである。でも当社の主な利用の場合、読み込み、操作の揮発性会員。一度チェックの存在は、その値を返す.


private static volatile MySingleton INSTANCE;

public static MySingleton getInstance() {
    MySingleton result = INSTANCE;
    if (result == null) {
        synchronized(MySingleton.class) {
            result = INSTANCE;
            if (result == null) {
                INSTANCE = result = createInstance();
            }
        }
    }

    return result;
}

以降のパフォーマンスによる営業の揮発性員ましょうローカル変数の値の変動のローカル変数です。この回数を減らし、揮発性を再生一部を失った。ることに注意して設定をしていて、局所変数を入力の同期化ブロックです。これまでの日付変更が発生した、ロックが解除されます。

私は記事を書いた本です。 脱構築"のシングルトン.また、この情報をこれらの例は、例の"ホルダー"のパターンあります。また実例紹介のダブルチェック揮発性です。武器agiは、dexで下がらないboxerぐ.

There are 4 ways to create a singleton in java.

1- eager initialization singleton

    public class Test{
        private static final Test test = new Test();
        private Test(){}
        public static Test getTest(){
            return test;
        }
    }

2- lazy initialization singleton (thread safe)

    public class Test {
         private static volatile Test test;
         private Test(){}
         public static Test getTest() {
            if(test == null) {
                synchronized(Test.class) {
                    if(test == null){test = new Test();
                }
            }
         }

        return test;
    }


3- Bill Pugh Singleton with Holder Pattern (Preferably the best one)

    public class Test {

        private Test(){}

        private static class TestHolder{
            private static final Test test = new Test();
        }

        public static Test getInstance(){
            return TestHolder.test;
        }
    }

4- enum singleton
      public enum MySingleton {
        INSTANCE;
    private MySingleton() {
        System.out.println("Here");
    }
}

この実装方法の簡単な singleton:

public class Singleton {
    // It must be static and final to prevent later modification
    private static final Singleton INSTANCE = new Singleton();
    /** The constructor must be private to prevent external instantiation */ 
    private Singleton(){}
    /** The public static method allowing to get the instance */
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

この方法を適切に怠け者を singleton:

public class Singleton {
    // The constructor must be private to prevent external instantiation   
    private Singleton(){}
    /** The public static method allowing to get the instance */
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
    /** 
     * The static inner class responsible for creating your instance only on demand,
     * because the static fields of a class are only initialized when the class
     * is explicitly called and a class initialization is synchronized such that only 
     * one thread can perform it, this rule is also applicable to inner static class
     * So here INSTANCE will be created only when SingletonHolder.INSTANCE 
     * will be called
     */
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
}

必要なもの ダブルチェック 熟が必要な場合は負荷のインスタンス変数のクラスは、遅延してもかまいません。が必要な場合荷重を静的変数はシングルトンは、遅延が必要 initilizationマホルダー ム.

また、シングルトンのニーズにseriliazble、他のすべての分野のニーズに一過性readResolve()メソッドを実施することが必要となりを維持するためには、シングルトンオブジェクト不変な場合。そうでない場合、時間のオブジェクトが直列化復元は、新しいインスタンスのオブジェクトを作成します。何readResolve()な置き換え、新しいオブジェクトが読み取るreadObject()を強制する新しいオブジェクトへのごみの収集はありませんの変数を参照します。

public static final INSTANCE == ....
private Object readResolve() {
  return INSTANCE; // original singleton instance.
} 

様々な方法をシングルトンオブジェクト:

  1. していたジョシュア-ブロッホ-Enumうのが一番よいと思います。

  2. 利用できるダブルチェックロックもございます

  3. でも内部の静的クラスを使用できます。

Enumシングルトン

最も簡単な方法を実施するシングルトンはスレッドの安全な使用の列挙型

public enum SingletonEnum {
  INSTANCE;
  public void doSomething(){
    System.out.println("This is a singleton");
  }
}

このコードの導入以来、Enum Java1.5

ダブルルクロック

したい場合はコードの"クラシック"シングルトンを作ることは、並行マルチスレッド環境からJava1.5)にするべき使用されます。

public class Singleton {

  private static volatile Singleton instance = null;

  private Singleton() {
  }

  public static Singleton getInstance() {
    if (instance == null) {
      synchronized (Singleton.class){
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance ;
  }
}

これはスレッドセーフではありません前1.5での実施の揮発性キーワードをなすものである。

早期負荷シングルトン(動作前であってもJava1.5)

この実装はinstantiatesのシングルトンのクラスがロードされ、スレッドの安全性です。

public class Singleton {

  private static final Singleton instance = new Singleton();

  private Singleton() {
  }

  public static Singleton getInstance() {
    return instance;
  }

  public void doSomething(){
    System.out.println("This is a singleton");
  }

}

のためのJSE5.0以上の列挙型アプローチ、それ以外の利用静的シングルトンホルダーアプローチ(怠け者の負荷に記載のアプローチによる法案ピュー).後者の解決にもスレッドの安全な言語を構築します(揮発性または同期化).

他の引数はしばしば対Singletonsそtestabilityます。Singletons容易ではありませんmockableのための試験。これが問題にされている以下の若干の修正:

public class SingletonImpl {

    private static SingletonImpl instance;

    public static SingletonImpl getInstance() {
        if (instance == null) {
            instance = new SingletonImpl();
        }
        return instance;
    }

    public static void setInstance(SingletonImpl impl) {
        instance = impl;
    }

    public void a() {
        System.out.println("Default Method");
    }
}

に追加 setInstance メソッドを使用すると設定モックアップ実装のシングルトンクラス中試験

public class SingletonMock extends SingletonImpl {

    @Override
    public void a() {
        System.out.println("Mock Method");
    }

}

この初期の初期化方法:

public class SingletonImpl {

    private static final SingletonImpl instance = new SingletonImpl();

    private static SingletonImpl alt;

    public static void setInstance(SingletonImpl inst) {
        alt = inst;
    }

    public static SingletonImpl getInstance() {
        if (alt != null) {
            return alt;
        }
        return instance;
    }

    public void a() {
        System.out.println("Default Method");
    }
}

public class SingletonMock extends SingletonImpl {

    @Override
    public void a() {
        System.out.println("Mock Method");
    }

}

この欠点が露出この機能は、通常のアプリケーションです。他のデベロッパーに取り組んでいるハードウェアコンに誘惑されることを利用setInstance方法の変更の変更特定の機能が変化するの応用行動、そのため、このメソッドは少なくとも良いで警告を発するものjavadoc.

ものがモックアップ試験が必要)このコードの露光が可能価額の支払い

単純なシングルトンクラス

public class Singleton {
  private static Singleton singleInstance = new Singleton();
  private Singleton() {}
  public static Singleton getSingleInstance() {
    return singleInstance;
  }
}

たなければならないと思い後のjava1.5、enumのシングルトン実装を可能とすることでも、マルチスレッドの環境でひとつだけのインスタンスが作成されます。

public enum Singleton{ INSTANCE; }

すっ!!!

しています。

例GoFデザインパターンにJavaのコア図書館

からの最良の答えは"シングルトン"、

シングルトン(recognizeableによるcreational方法を返し同じインスタンス(通常の)とct)

  • java.lang.Runtime#getRuntime()
  • java.awt.デスクトップ#getDesktop()
  • java.lang.システム#getSecurityManager()

あなたも学ぶことができ、例のシングルトンからJava nativeの授業です。

最高のシングルトンパターンからのサプライヤインターフェース。

  • で汎用及び再利用
  • このぐさの初期化
  • この同期まで初期化され、その後のブロックサプライヤに交換された非ブロックカテゴリーに入るホテルです。

ついて(通知)"がありました。

public class Singleton<T> implements Supplier<T> {

    private boolean initialized;
    private Supplier<T> singletonSupplier;

    public Singleton(T singletonValue) {
        this.singletonSupplier = () -> singletonValue;
    }

    public Singleton(Supplier<T> supplier) {
        this.singletonSupplier = () -> {
            // The initial supplier is temporary; it will be replaced after initialization
            synchronized (supplier) {
                if (!initialized) {
                    T singletonValue = supplier.get();
                    // Now that the singleton value has been initialized,
                    // replace the blocking supplier with a non-blocking supplier
                    singletonSupplier = () -> singletonValue;
                    initialized = true;
                }
                return singletonSupplier.get();
            }
        };
    }

    @Override
    public T get() {
        return singletonSupplier.get();
    }
}

時には簡単な"static Foo foo = new Foo();"いのではない。も基本的なデータを挿入します。

のように同期させる、あらゆる手法によるinstantiatesのシングルトンを可変しています。Synchronisationは悪くないあなたがすることができるパフォーマンス問題やロックにも非常に珍しい状況での使用例です。解決には

public class Singleton {

    private static Singleton instance = null;

    static {
          instance = new Singleton();
          // do some of your instantiation stuff here
    }

    private Singleton() {
          if(instance!=null) {
                  throw new ErrorYouWant("Singleton double-instantiation, should never happen!");
          }
    }

    public static getSingleton() {
          return instance;
    }

}

今、何が起きているのでしょうか。のクラスがロードされ、クラスローダを使用します。直後のクラスが解釈されるバイト配列から、VMの実行 静{} -ブロックです。その秘密:の静的-ブロックにのみ呼び出すことに時間を指定されたクラス名の指定されたパッケージが読み込まれるこのクラスローダを使用します。

public class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton(){
    if (INSTANCE != null)
        throw new IllegalStateException (“Already instantiated...”);
}

    public synchronized static Singleton getInstance() { 
    return INSTANCE;

    }

}

として追加、同期をキーワードの前にgetInstanceして回避され、レース状態の場合は二つのスレッドを呼び出getInstanceでも同時に行います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top