欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)單例模式之餓漢式、懶漢式、枚舉式

 更新時間:2016年10月25日 15:08:32   作者:我只是一名程序員  
本篇文章主要介紹了Java實現(xiàn)單例的3種普遍的模式,餓漢式、懶漢式、枚舉式。具有一定的參考價值,感興趣的小伙伴們可以參考一下。

單例模式的實現(xiàn)(5種)

常用:

餓漢式(線程安全,調(diào)用效率高,但是不能延時加載)
懶漢式(線程安全,調(diào)用效率不高,可以延時加載)

其他:

雙重檢測鎖式(由于jvm底層內(nèi)部模型原因,偶爾會出問題,不建立使用)
靜態(tài)內(nèi)部類式(線程安全,調(diào)用效率高,但是可以延時加載)
枚舉單例(線程安全,調(diào)用效率高,不能延時加載)
餓漢式單例具體代碼如下:

package com.lcx.mode; 
 
 
/** 
 * 
 * 餓漢式單例,不管以后用不用這個對象,我們一開始就創(chuàng)建這個對象的實例, 
 * 需要的時候就返回已創(chuàng)建好的實例對象,所以比較饑餓,故此叫餓漢式單例。 
 * @author qq1013985957 
 * 
 */ 
public class SingletonHanger { 
  private static final SingletonHanger instance = new SingletonHanger(); 
  private SingletonHanger() { 
  } 
  public static SingletonHanger getInstance(){ 
    return instance; 
  } 
} 
/** 
 * 懶漢漢式單例,在需要單例對象的時候,才創(chuàng)建唯一的單例對象,以后再次調(diào)用,返回的也是第一創(chuàng)建的單例對象 
 * 將靜態(tài)成員初始化為null,在獲取單例的時候才創(chuàng)建,故此叫懶漢式。 
 * @author qq1013985957 
 * 
 */ 
class SingletonLazy{ 
  private static SingletonLazy instance = null; 
  private SingletonLazy() { 
  } 
  /** 
   * 此方法實現(xiàn)的單例,無法在多線程中使用,多線可以同時進入if方法,會導(dǎo)致生成多個單例對象。 
   * @return 
   */ 
  public static SingletonLazy getInstance1(){ 
    if(instance==null){ 
      instance = new SingletonLazy(); 
    } 
    return instance; 
  } 
  /** 
   * 大家都會想到同步,可以同步方法實現(xiàn)多線程的單例 
   * 但是這種方法不可取,嚴重影響性能,因為每次去取單例都要檢查方法,所以只能用同步代碼塊的方式實現(xiàn)同步。 
   * @return 
   */ 
  public static synchronized SingletonLazy getInstance2(){ 
    if(instance==null){ 
      instance = new SingletonLazy(); 
    } 
    return instance; 
  } 
  /** 
   * 用同步代碼塊的方式,在判斷單例是否存在的if方法里使用同步代碼塊,在同步代碼塊中再次檢查是否單例已經(jīng)生成, 
   * 這也就是網(wǎng)上說的 雙重檢查加鎖的方法 
   * @return 
   */ 
  public static synchronized SingletonLazy getInstance3(){ 
    if(instance==null){ 
      synchronized (SingletonLazy.class) { 
        if(instance==null){ 
          instance = new SingletonLazy(); 
        } 
      } 
    } 
    return instance; 
  } 
} 
/** 
 * 
 * 使用枚舉實現(xiàn)單例模式,也是Effective Java中推薦使用的方式 
 * 根據(jù)具體情況進行實例化,對枚舉不熟悉的同學(xué),可以參考我的博客 JAVA 枚舉類的初步理解。 
 * 它的好處:更加簡潔,無償提供了序列化機制,絕對防止多次實例化,即使面對復(fù)雜的序列和反射攻擊。 
 * @author qq1013985957 
 * 
 */ 
enum SingletionEnum{ 
  SingletionEnum("單例的枚舉方式"); 
  private String str ; 
  private SingletionEnum(String str){ 
    this.setStr(str); 
  } 
  public String getStr() { 
    return str; 
  } 
  public void setStr(String str) { 
    this.str = str; 
  } 
   
} 

以上的單例模式就不測試,大家可以去測試,判斷對象的hashcode是否一致來判斷是否為同一個對象。

惡漢式、懶漢式的方式還不能防止反射來實現(xiàn)多個實例,通過反射的方式,設(shè)置ACcessible.setAccessible方法可以調(diào)用私有的構(gòu)造器,可以修改構(gòu)造器,讓它在被要求創(chuàng)建第二個實例的時候拋出異常。

其實這樣還不能保證單例,當序列化后,反序列化是還可以創(chuàng)建一個新的實例,在單例類中添加readResolve()方法進行防止。
懶漢漢式單例代碼如下:

package com.lcx.mode; 
 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 
 
/** 
 * 懶漢漢式單例,在需要單例對象的時候,才創(chuàng)建唯一的單例對象,以后再次調(diào)用,返回的也是第一創(chuàng)建的單例對象 
 * 將靜態(tài)成員初始化為null,在獲取單例的時候才創(chuàng)建,故此叫懶漢式。 
 * @author qq1013985957 
 * 
 */ 
public class Singleton implements Serializable{ 
  /** 
   * 
   */ 
  private static final long serialVersionUID = -5271537207137321645L; 
  private static Singleton instance = null; 
  private static int i = 1; 
  private Singleton() { 
    /** 
     * 防止反射攻擊,只運行調(diào)用一次構(gòu)造器,第二次拋異常 
     */ 
    if(i==1){ 
      i++; 
    }else{ 
      throw new RuntimeException("只能調(diào)用一次構(gòu)造函數(shù)"); 
    } 
    System.out.println("調(diào)用Singleton的私有構(gòu)造器"); 
     
  } 
  /** 
   * 用同步代碼塊的方式,在判斷單例是否存在的if方法里使用同步代碼塊,在同步代碼塊中再次檢查是否單例已經(jīng)生成, 
   * 這也就是網(wǎng)上說的 雙重檢查加鎖的方法 
   * @return 
   */ 
  public static synchronized Singleton getInstance(){ 
    if(instance==null){ 
      synchronized (Singleton.class) { 
        if(instance==null){ 
          instance = new Singleton(); 
        } 
      } 
    } 
    return instance; 
  } 
  /** 
   * 
   * 防止反序列生成新的單例對象,這是effective Java 一書中說的用此方法可以防止,具體細節(jié)我也不明白 
   * @return 
   */ 
  private Object readResolve(){ 
    return instance; 
  } 
  public static void main(String[] args) throws Exception { 
    test1(); 
    test2(); 
  } 
  /** 
   * 測試 反序列 仍然為單例模式 
   * @throws Exception 
   */ 
  public static void test2() throws Exception{ 
    Singleton s = Singleton.getInstance(); 
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("E:\\Singleton.txt"))); 
    objectOutputStream.writeObject(s); 
    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("E:\\Singleton.txt"))); 
    Object readObject = objectInputStream.readObject(); 
    Singleton s1 = (Singleton)readObject; 
    System.out.println("s.hashCode():"+s.hashCode()+",s1.hashCode():"+s1.hashCode()); 
     
    objectOutputStream.flush(); 
    objectOutputStream.close(); 
    objectInputStream.close(); 
  } 
  /** 
   * 測試反射攻擊 
   * @throws Exception 
   */ 
  public static void test1(){ 
    Singleton s = Singleton.getInstance(); 
    Class c = Singleton.class; 
    Constructor privateConstructor; 
    try { 
      privateConstructor = c.getDeclaredConstructor(); 
      privateConstructor.setAccessible(true); 
      privateConstructor.newInstance(); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
} 

驗證反射攻擊結(jié)果:

如果不添加readResolve方法的結(jié)果:

添加readResolve方法的結(jié)果:

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • java-SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁

    java-SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁

    本文主要是介紹SSH2實現(xiàn)數(shù)據(jù)庫和界面的分頁的代碼,分頁在web應(yīng)用中是經(jīng)常要做的事情,實用性比較大,有需要的朋友可以來了解一下。
    2016-10-10
  • java開源項目jeecgboot的超詳細解析

    java開源項目jeecgboot的超詳細解析

    JeecgBoot是一款基于BPM的低代碼平臺,下面這篇文章主要給大家介紹了關(guān)于java開源項目jeecgboot的相關(guān)資料,文中通過圖文以及實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • java 中自定義OutputFormat的實例詳解

    java 中自定義OutputFormat的實例詳解

    這篇文章主要介紹了java 中 自定義OutputFormat的實例詳解的相關(guān)資料,這里提供實例幫助大家學(xué)習(xí)理解這部分內(nèi)容,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-08-08
  • 淺談java中的TreeMap 排序與TreeSet 排序

    淺談java中的TreeMap 排序與TreeSet 排序

    下面小編就為大家?guī)硪黄獪\談java中的TreeMap 排序與TreeSet 排序。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • 簡單講解奇偶排序算法及在Java數(shù)組中的實現(xiàn)

    簡單講解奇偶排序算法及在Java數(shù)組中的實現(xiàn)

    這篇文章主要介紹了奇偶排序算法及Java數(shù)組的實現(xiàn),奇偶排序的時間復(fù)雜度為O(N^2),需要的朋友可以參考下
    2016-04-04
  • Java實現(xiàn)等待所有子線程結(jié)束后再執(zhí)行一段代碼的方法

    Java實現(xiàn)等待所有子線程結(jié)束后再執(zhí)行一段代碼的方法

    這篇文章主要介紹了Java實現(xiàn)等待所有子線程結(jié)束后再執(zhí)行一段代碼的方法,涉及java多線程的線程等待與執(zhí)行等相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • 淺談SpringBoot實現(xiàn)異步調(diào)用的幾種方式

    淺談SpringBoot實現(xiàn)異步調(diào)用的幾種方式

    本文主要介紹了淺談SpringBoot實現(xiàn)異步調(diào)用的幾種方式,主要包括CompletableFuture異步任務(wù),基于@Async異步任務(wù), TaskExecutor異步任務(wù),感興趣的可以了解一下
    2023-11-11
  • SpringBoot中的@PreAuthorize注解詳解

    SpringBoot中的@PreAuthorize注解詳解

    這篇文章主要介紹了SpringBoot中的@PreAuthorize注解詳解,@PreAuthorize注解會在方法執(zhí)行前進行權(quán)限驗證,支持Spring?EL表達式,它是基于方法注解的權(quán)限解決方案,需要的朋友可以參考下
    2023-09-09
  • SpringBoot中Bean拷貝及工具類封裝的實現(xiàn)

    SpringBoot中Bean拷貝及工具類封裝的實現(xiàn)

    本文主要介紹了SpringBoot中Bean拷貝及工具類封裝的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • JavaEE在線人數(shù)管理系統(tǒng)

    JavaEE在線人數(shù)管理系統(tǒng)

    這篇文章主要為大家分享了JavaEE在線人數(shù)管理系統(tǒng),顯示在線人數(shù)、在線人詳細信息、管理員踢人等功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09

最新評論