1. 程式人生 > >手寫單例——面試考點

手寫單例——面試考點

設計模式
1.單例設計模式(重點:面試的時候總是會手寫單例)
                            ——一定要掌握雙重檢查、靜態內部類、列舉這三種寫法
概念:一個類只能例項化一個物件
(1) 立即初始化 ->餓漢式單利->立即載入,執行緒安全,記憶體可能會浪費

public class Singleton1 {
    //將這個類的構造方法定義為私有的,就只能建立一個物件
    private static final Singleton1 INSTANCE =new Singleton1();//1
    private  Singleton1(){

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

}

(2) 延遲例項化 ->懶漢式:->執行緒不安全,可能不使用物件時可以減少記憶體空間
/**

  • 懶漢式:延遲例項化,執行緒不安全(當有多個執行緒同時訪問的時候,同時發現是null的時候,都會例項化一個,這時候執行緒就在來回變化)
  • 但是在不使用物件時可以節省記憶體空間
 * Author:WSChase
 * Created:2018/11/26
 */
public class Singleton2 {
    private static Singleton2 instance =null;
    private Singleton2(){

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


我們在設計這個方法的時候,它的構造方法用private修飾,這個時候在另外一個類裡面不可以建立物件
所以我們在這個類裡面用一個公有的方法返回一個建立的物件,在本類裡面我們可以訪問private。
注意:一定要掌握懶漢式雙重檢查的方式或者是靜態內部類的寫法、列舉的寫法
靜態內部類的寫法:

public SingleTon{
private static SingleTon(){

}
public static void getInstance(){
return 
}
public static SingleTon1{
return new SingleTon();//返回一個物件
}
}


寫單例的注意事項:
(1)構造方法私有
(2)提供public static 獲取例項化物件的方法
(3)類的內部例項化物件

package desinpattern;

/**
 * 1.一個類只允許例項化一個物件
 * 2.立即初始化->餓漢式單例->可以立即載入,執行緒安全,記憶體可能會浪費(如果沒有人去呼叫這個函式,那麼這個函式中已
 * 經開闢了空間了,就會浪費)
 * Author:WSChase
 * Created:2018/11/26
 */
////1.靜態常量
//public class Singleton1 {
//    //將這個類的構造方法定義為私有的,就只能建立一個物件
//    private static final Singleton1 INSTANCE =new Singleton1();//1
//    private  Singleton1(){
//
//    }
//    public static Singleton1 getInstance() {
//        return INSTANCE;
//    }
//
//}
//如果採用靜態常量的寫法,會造成浪費記憶體

//2.餓漢式
 * Author:WSChase
 * Created:2018/11/26
 */
public class Singleton2 {
    private static Singleton2 instance =null;
    private Singleton2(){

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


////3.(執行緒不安全)
//public class Singleton1{
//    private static Singleton1 singleton;
//    private Singleton1(){}
//    public static Singleton1 getInstance(){
//        if(singleton==null){
//            singleton=new Singleton1();
//        }
//        return singleton;
//    }
//}
////這種寫法之所以是執行緒不安全的是因為,當我們同時有多個執行緒訪問
////if(singleton==null)這個語句的時候,同時發現物件並沒有例項化
////這時候多個執行緒就會進行例項化,那麼就會例項化多個物件,造成不安全
////4.執行緒安全,同步方法
//public class Singleton1{
//    private static Singleton1 singleton;
//    private Singleton1(){}
//    public static synchronized Singleton1 getInstance(){
//        if(singleton==null){
//            singleton=new Singleton1();
//        }
//        return singleton;
//    }
//}
////對於第三種情況之所以會出現執行緒不安全的原因就是因為執行緒不同步,
////所以我們用synchronized進行修飾方法就可以保證這個方法是執行緒同步的了,
////這樣自然就解決了執行緒不安全的問題。但是這樣的寫法也會有弊端,即使效率太低了,
////因為如果多個執行緒同時訪問這個語句,那麼就意味著一次只能有一個執行緒可以進行例項化物件,
////剩下的執行緒就必須等待。

////5.執行緒安全,同步程式碼塊
//public class Singleton1{
//    private static Singleton1 singleton;
//    private Singleton1(){}
//    public static Singleton1 getInstance(){
//        if(singleton==null){
//            synchronized (Singleton1.class){
//                singleton=new Singleton1();
//            }
//        }
//        return singleton;
//    }
//}
////這種同步程式碼塊的寫法並不能保證執行緒安全,它同樣會出現和第3種一樣的情況,所以它並不可取。
////6.雙重檢查——一定要掌握
//public class Singleton1{
//    private static volatile Singleton1 singleton;
//    private Singleton1(){
//
//    }
//    public static Singleton1 getInstance(){
//        //雙重檢查
//        if(singleton==null){
//            synchronized (Singleton1.class){
//                if(singleton==null){
//                    singleton=new Singleton1();
//                }
//            }
//        }
//        return singleton;
//    }
//}
////這樣的寫法既可以保證執行緒安全,又提高了效率。在進行雙重檢查執行了兩次if(singleton==null),在第一次檢查
////的時候是延遲了載入,第二次檢查的時候如果卯足條件直接例項化物件。

////7.靜態內部類
//public class Singleton1 {
//    private Singleton1() {
//
//    }
//
//    private static class SingletonInstance {
//        private static final Singleton INSTANCE = new Singleton();
//
//    }
//    public static Singleton getInstance(){
//        return SingletonInstance.INSTANCE;
//    }
//}
////這個方法的原理機制和餓漢式很像,只會在第一次載入類的時候初始化,JVM保證了執行緒的安全性,
////靜態內部類方式在Sindleton1類裝載的時候並不會立即例項化,而是在需要例項化時,呼叫getInstance方法,
////之後裝載SingletonInstance類才會完成例項化。

//8.列舉
public enum Singleton1{
    INSTANCE;
    public void method(){
        
    }
}
//可以避免多執行緒同步問題,而且可以防止反序列化重新建立新物件。