Javaのシングルトンデザインパターン8通り

シングルトンデザインパターン入門

、クラスと呼ばれるシングルトンデザインパターンは、オブジェクトのインスタンスの唯一特定のクラスがあり、全体のソフトウェアシステムを確保するための特定の方法を取ることであり、クラスは、そのオブジェクトのインスタンスを取得する唯一の方法(静的メソッド)を提供します。
このようなHibernateのSessionFactoryのように、プロキシデータ貯蔵源として機能し、Sessionオブジェクトを作成するための責任があります。SessionFactoryの軽量ではないが、通常の状況下では、プロジェクトは通常のみのSessionFactoryを必要十分で、これはシングルトンに使用されますされています。

シングルトンデザインパターン8通り

パターンシングルトン8つの方法があります。

  1. 飢餓式((スタティックCONST))
  2. 飢餓式(静的コードブロック)
  3. 怠惰な人間の(スレッドセーフ)
  4. レイジー男の(スレッドセーフ、同期方法)
  5. レイジー式(スレッドセーフ、同期ブロック)
  6. ダブルチェック
  7. 静的な内部クラス
  8. 列挙

1.飢餓式(静的定数)

空腹の人型(静的定数)適用例

次のステップ:

1)民営化コンストラクタ()新しい防止
オブジェクトクラスを作成するために)2の内部
3)外向きパブリック静的メソッドを露出します。getInstance

コードの実装

class SingletonTest01 {

    public static void main(String[] args) {
        //测试
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

//饿汉式(静态变量)

class Singleton {

    //1. 构造器私有化, 外部能new
    private Singleton() {

    }

    //2.本类内部创建对象实例
    private final static Singleton instance = new Singleton();

    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }

}

長所と短所を説明します。

  1. 利点:このようなアプローチは、負荷がクラスがインスタンス化された完了したとき、すなわち、比較的簡単です。スレッドの同期の問題を回避するには。
  2. デメリット:クラスがインスタンス化されるのロードが完了すると、効果が遅延読み込みに達しありませんでした。あなたが最初から最後まで、この例を使用したことがない場合は、メモリの無駄になります
  3. このようにしclassloderメカニズムに基づいて、ほとんどの場合、シングルモードは、getInstanceメソッドを呼び出しているが、クラスがロードされているいくつかの理由があり、それゆえすることはできません、しかし、クラスのインスタンスへのインスタンスを一度にロードされ、同期の問題マルチスレッドを回避クラスローダ原因を決定する他の方法(または他の静的メソッド)がある、それは怠惰なローディング効果の初期化インスタンスに到達しないだろう

結論:

本実施の形態では、単独で使用することができ、それは無駄なメモリをもたらすことができます


2.飢餓式(静的コードブロック)

コードの実装

package com.jfjb.singleton.type1;

class SingletonTest01 {

    public static void main(String[] args) {
        //测试
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

//饿汉式(静态变量)

class Singleton {

    //1. 构造器私有化, 外部能new
    private Singleton() {

    }

    //2.本类内部创建对象实例
    private  static Singleton instance;

    static { // 在静态代码块中,创建单例对象
        instance = new Singleton();
    }

    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }

}

長所と短所を説明します。

  1. このように上記のように、それは実際には非常に似ている、コードブロック静的コード、インスタンスの初期化クラスを実行するために、クラスのプロセスは、クラスがロードされた静的コードブロック、上でインスタンス化されることを除い。長所と短所と上記と同じです。

    結論:

    この利用できるシングルケースモデルが、無駄なメモリをもたらすことができます


3.怠惰な人間の(スレッドセーフ)

コードの実装

class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("懒汉式1 , 线程不安全~");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

class Singleton {
    private static Singleton instance;

    private Singleton() {}

    //提供一个静态的公有方法,当使用到该方法时,才去创建 instance
    //即懒汉式
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

長所と短所を説明します。

  1. 遅延ロードは効果を果たしたが、唯一のシングルスレッドで使用することができます。
  2. 、if文ブロックを解析する場合(シングルトン== NULL)へのマルチスレッド、スレッドで、ダウン実行するための時間を持っていただけでなく、別のスレッドによってこの文の解析時間インスタンスを複数生成します。だから、マルチスレッド環境でこのように使用することはできません

結論:

実際の開発では、このアプローチを使用しないでください。


4.ハンレイジー式(スレッドセーフ、同期方法)

コードの実装

public class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("懒汉式2 , 线程安全~");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static Singleton instance;

    private Singleton() {}

    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

長所と短所を説明します。

1)不安スレッドの問題解決への
2)効率が低すぎる、とのgetInstance()メソッドを同期させる必要があります実装するクラスの時間の各スレッドのインスタンスに取得したいです。そして、実際には、コードのインスタンスが十分にある。この方法で一度だけ、私はライン上のインスタンス、直接リターンのこの種の後ろに取得したいです。同期させるために非効率的な方法

結論:

実際の開発では、このように推奨されていません


5.ハンレイジー式(スレッドセーフ、同期ブロック)

コードの実装

// 懒汉式(线程安全,同步代码块)
class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

長所と短所を説明します。

1)このようにして、インスタンス化された同期コード・ブロック生成する低すぎる効率としてフロント同期方法、第四の実施を改善するために意図されていた
が、このような同期は、スレッドの同期の役割を再生することはできません)2 。スレッドがあれば(シングルトン== nullの)判断文ブロック、ダウンを実行しないように十分な時間を入力した場合第三のシナリオは、実装経験と一致している、また、裁判官の判決を通過した別のスレッドでは、この時間が生成されます複数のインスタンス

結論:

実際の開発では、このように使用することはできません


6.ダブルチェック(推奨)

コードの実装

public class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("双重检查");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());

    }

}

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
    //同时保证了效率, 推荐使用

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

        }
        return instance;
    }
}

長所と短所を説明します。

コードに示すように、1)ダブルチェック概念は、多くの場合、マルチスレッド開発するために使用され、我々は、セキュリティスレッドを確保するように、2であれば(シングルトン== null)の検討を行いました。
。後で再度アクセスしたとき(シングルトン== NULL)は、直接リターン・オブジェクト・インスタンスが、この方法は、繰り返し同期を回避する場合2)このように、インスタンス化コードは一度だけ、それが判断され
、遅延ローディング; 3)セキュリティ・スレッドよりも効率的高いです

結論:

実際の開発では、これはデザインパターンシングルトンをお勧めします


7.静的な内部クラス(推奨)

コードの実装

public class SingletonTest01 {

    public static void main(String[] args) {
        System.out.println("使用静态内部类完成单例模式");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());

    }

}

// 静态内部类完成, 推荐使用
class Singleton {
    private static volatile Singleton instance;

    //构造器私有化
    private Singleton() {
    }

    //写一个静态内部类,该类中有一个静态属性 Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    public static synchronized Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

長所と短所を説明します。

1) 这种方式采用了类装载的机制来保证初始化实例时只有一个线程。
2) 静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
3) 类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
4) 优点:避免了 线程不安全,利用静态内部类特点实现延迟加载,效率高

结论:

推荐使用.


8. 枚举(推荐)

代码实现

public class SingletonTest01 {
    public static void main(String[] args) {
        Singleton instance = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        System.out.println(instance == instance2);

        System.out.println(instance.hashCode());
        System.out.println(instance2.hashCode());

        instance.sayOK();
    }
}

//使用枚举,可以实现单例, 推荐
enum Singleton {
    INSTANCE; //属性
    public void sayOK() {
        System.out.println("ok~");
    }
}

优缺点说明:

1) 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
2) 这种方式是Effective Java作者Josh Bloch 提倡的方式

结论:

推荐使用


在JDK 应用的源码分析

我们JDK中,java.lang.Runtime就是经典的单例模式(饿汉式)

单例模式注意事项和细节说明

1) 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
2) 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
3) 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)


参考基于尚硅谷Java设计模式,韩顺平图解java设计模式

おすすめ

転載: www.cnblogs.com/ifme/p/12433324.html
おすすめ