05.同時プログラミングの一例とマルチスレッド

4195 ワード

1、ThreadLocal


スレッドローカル変数は、マルチスレッド間で変数に同時アクセスするソリューションであり、synchronizedのロック方式とは異なり、ThreadLocalはロックを全く提供せず、空間で時間を変える手段を使用して、各スレッドに変数の独立したコピーを提供し、スレッドの安全を保障する.性能の面から言えば、ThreadLocalは絶対的な優位性を持たず、合併があまり高くない場合、ロック性能はもっと良いが、高合併や競争が激しい場合、ハードウェアが優れている場合、ThreadLocalでロック競争をある程度減らす.

2、単例モード


単例モードの飢餓と怠け者モードはマルチスレッドではだめで、性能が高くなく、スレッドの安全静的内部クラスモードを保証できない.推奨、最も安全、最も信頼できる.
    public class InnerSingleton {
        private static class Singleton {
            private static Singleton single = new Singleton();
        }
        public static Singleton getInstance() {
            return Singleton.single;
        }
    }
     :
    package demo2;

    public class MySingleTon {

        // 1:   , ,getInstance 

        private final static MySingleTon singleTon = new MySingleTon();

        private MySingleTon() {
            System.out.println("starting init single");
        }

        public static MySingleTon getInstance() {
            return singleTon;
        }

        public static void main(String[] args) {
            System.out.println("-------------");
            MySingleTon sinle1 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle2 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle3 = MySingleTon.getInstance();
        }
    }
     :
    starting init single
    -------------
    -------------
    -------------
    
    package demo2;

    public class MySingleTon {

        // 2      getInstance   

        private static MySingleTon single = null;

        private MySingleTon() {
            System.out.println("starting init single");
        }

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

        public static void main(String[] args) {
            System.out.println("-------------");
            MySingleTon sinle1 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle2 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle3 = MySingleTon.getInstance();
        }
    }
     
    -------------
    starting init single
    -------------
    -------------
    public class Singleton  
    {  
        private Singleton(){ }  
        
        public static Singleton getInstance()  
        {  
            return Nested.instance;       
        }  
        
        //   
        static class Nested  
        {  
            private static Singleton instance = new Singleton();  
        }  
        
        public static void main(String args[])  
        {  
            Singleton instance = Singleton.getInstance();  
            Singleton instance2 = Singleton.getInstance();  
            System.out.println(instance == instance2);  
        }  
    }  

3、1、2、3の3つの実現については、いくつかの違いがあります。

  • 第1種:餓漢式はクラスの作成と同時に静的オブジェクトをインスタンス化し、その後この単例を使用するかどうかにかかわらず一定のメモリを占有するが、それに応じて、最初の呼び出し時に速度も速くなる.そのリソースは初期化済みであるため、
  • の2つ目は、getInstanceでnullチェックを2回行い、1回目の呼び出し例の場合にのみ同期を行うことを確保するスレッドが安全であるとともに、毎回同期する性能損失
  • を回避する.
  • 第3種は、classloaderのメカニズムを利用してinstanceを初期化する際に1つのスレッドしかないことを保証しているので、スレッドが安全であり、性能損失がないので、一般的に私はこの1種を使用する傾向があります.

  • PS1
    内部クラスによって単一の例を実現する方法であって、静的内部クラスは外部クラスの静的メソッドと静的属性にしかアクセスできない.現在では,この特性を用いて単一例モードを実現するのが一般的である.クラスは初期化時にスレッドが反発するため、単一の例が衝突を作成する問題を完璧に解決することができます.
    PS2
    単例モードは一般的なモードであり、怠け者モードはスレッドセキュリティを考慮して単例を取得する方法にsynchronizedキーワードを追加して同期コードブロックを実現する必要があり、これにより性能損失をもたらす.餓漢モードはインスタンス化対象を遅らせることができず,静的内部クラスの単例モードの実現は,スレッドの安全を保証し,ロードを遅らせることができる,すなわち初めて使用したときにロードすることができる.