デザインパターン-シングルトンパターンの簡単な紹介

シングルトンモードの原理

シングルトンオブジェクトとは何ですか?

一部のオブジェクトでは、スレッドプール、キャッシュdataSource、ハードウェアデバイスなどの1つだけが必要です。複数のインスタンスがある場合、競合や一貫性のない結果が発生します。結局のところ、あなたと私は持っていますが、あなたが持っているものと私が持っているものはまったく同じではないかもしれません。それらは同じです。シングルトンパターンを使用すると、クラスのインスタンスが最大で1つあることを確認し、グローバルアクセスポイントを提供できます。

public class Test {
    public class ABC {
        public ABC() {
        }

//        private ABC() {  //为这个内部类申明私有的构造方法,外部则无法通过new初始化,只能类自己初始化
//        }
//        ABC n1 = new ABC();
    }

    public class CDB {
        public CDB() {
            ABC n1, n2;
            n1 = new ABC();
            n2 = new ABC();
            System.out.println("CBD: " + (n1 == n2));    //false
        }
    }

    public static void main(String[] args) {
        ABC n1, n2;
        n1 = new Test().new ABC();
        n2 = new Test().new ABC();
        System.out.println("main: " + (n1 == n2));   //false
        new Test().new CDB();
    }
}

それで、新しいオブジェクトを毎回同じにする方法はありますか?以下のシングルトンパターンクラス図を見てください、あなたはいくつかのアイデアを見つけることができます!

シングルトン(シングルトン)
static uniqueInstance(静的一意オブジェクト宣言)
プライベートsingleton()(プライベートインスタンス化メソッド)
static getInstance()(グローバルアクセスポイント)

コーディング戦闘

上記の内容を理解した後、簡単なシングルトンモードコードを書いてみましょう。コードは次のとおりです。

public class Singleton {
    private static Singleton uniqeInstance = null;    //静态变量

    private Singleton() {    // 私有的构造方法,外部无法使用
    }

    public static Singleton getInstance() {
        if (uniqeInstance == null) {
            uniqeInstance = new Singleton();
        }
        return uniqeInstance;
    }
}

静的変数はどのインスタンスオブジェクトにも属していないため、クラスに属しているため、メモリ内のコピーは1つだけになります。クラスのロードプロセス中に、JVMは静的変数にメモリスペースを1回割り当てます。

このシナリオを想像してみましょう。食品工場、工場が1つ、ポットが1つだけです。食品のバッチを作成したら、次のバッチを作成できます。この時点で、食品工場のオブジェクトはシングルトンです。シミュレーションの実装は次のとおりです。コード、コードのシングルトン実装は上記の単純な実装とは異なり、最適化されています。後で最適化される理由を説明します。

public class ChocolateFactory {
    private boolean empty;   // 空锅
    private boolean boiled;  // 加热
    public volatile static ChocolateFactory uniqueInstance = null;

    private ChocolateFactory() {
        empty = true;    // 锅是空的
        boiled = false;  // 还没加热
    }

    public static ChocolateFactory getInstance() {
        if (uniqueInstance == null) {
            synchronized (ChocolateFactory.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new ChocolateFactory();
                }
            }
        }
        return uniqueInstance;
    }
    // 第一步装填
    public void fill() {
        if (empty) {  // 锅是空的
            // 添加原料巧克力动作
            empty = false;  // 锅装满了,不是空的
            boiled = false;  // 还没加热
        }
    }
    // 第三步倒出
    public void drain() {
        if ((!empty) && boiled) {  // 锅不是空的,已经加热
            // 排出巧克力动作
            empty = true;   //出锅,锅空了
        }
    }
    // 第二步加热
    public void boil() {
        if ((!empty) && (!boiled)) {  // 锅不是空的,没加热
            // 煮沸
            boiled = true;  // 已经加热
        }
    }
}

シングルトンモードの問題と最適化

問題

マルチスレッドの場合、タイムスライシングとcpu競合の概念がありますが、シングルトンモードで問題が発生する可能性がある場合、これはまさに何が起こるのでしょうか。例として食品加工工場のコードを取り上げます

public synchronized static ChocolateFactory getInstance() {
       if (uniqueInstance == null) {
           uniqueInstance = new ChocolateFactory();
       }
       return uniqueInstance;
   }

マルチスレッドの場合、2つのオブジェクトがインスタンス化されます

最適化されたソリューション

同期された(同期された)getInstanceメソッド

スレッド1を実行するif (uniqueInstance == null)と、スレッド2は実行権を奪われ、スレッド1は新しいオブジェクトを取得しません。スレッド2も同じように来てif (uniqueInstance == null)、オブジェクトのインスタンスを検出しませんでしたが、オブジェクトをインスタンス化する予定です。最後に、スレッド1スレッド2がuniqueInstance = new ChocolateFactory();この時点で実行されます。同期修飾子をれる前に追加のgetInstance()メソッド。しかし、この方法は、より性能のかかるマルチスレッドコールが頻繁にあります。

「熱心に」インスタンスを作成する

public class ChocolateFactory {
    public static ChocolateFactory uniqueInstance = new ChocolateFactory();  //“急切”创建实例
    public static ChocolateFactory getInstance() {
       if (uniqueInstance == null) {
           uniqueInstance = new ChocolateFactory();
       }
       return uniqueInstance;
   }
}

public static ChocolateFactory uniqueInstance = new ChocolateFactory();インスタンスオブジェクトは、アプリケーションの起動時に1回読み込まれ、初期化されます。このとき、if (uniqueInstance == null)結果は常にfalseであるため、マルチスレッド呼び出しには常に1つのインスタンスしかありません。ただし、シングルトンオブジェクトのペアがアプリケーションで使用されていない場合は、これを使用してください。メソッドはメモリスペースを消費します

再確認してロックする(最良)

public class ChocolateFactory {
    //用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。
    public volatile static ChocolateFactory uniqueInstance = null;   
    public static ChocolateFactory getInstance() {
        if (uniqueInstance == null) {
            synchronized (ChocolateFactory.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new ChocolateFactory();
                }
            }
        }
        return uniqueInstance;
    }
}

まずpublic volatile static ChocolateFactory uniqueInstance = null;、アプリケーションの起動時にオブジェクトが初期化されないため、メモリが節約されます。次に同期によって変更さたコードブロックが再度if (uniqueInstance == null) {}判断さ、条件が満たされた場合にのみ同期メソッドに入り、パフォーマンスの消費が削減されます。

おすすめ

転載: blog.csdn.net/doubututou/article/details/109210319