中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

淘寶客可道cms網(wǎng)站建設(shè)重慶seo整站優(yōu)化方案范文

淘寶客可道cms網(wǎng)站建設(shè),重慶seo整站優(yōu)化方案范文,哪個網(wǎng)站做h5號,基礎(chǔ)建設(shè)的網(wǎng)站有哪些文章目錄 單例模式的結(jié)構(gòu)如何控制只有一個對象呢怎么設(shè)計這個類的內(nèi)部對象外部怎么訪問 單例模式的主要有以下角色 單例模式的實現(xiàn)餓漢式 1:靜態(tài)變量餓漢式 2:靜態(tài)代碼塊懶漢式 1:線程不安全懶漢式 2:線程安全—方法級上鎖懶漢式 …

文章目錄

  • 單例模式的結(jié)構(gòu)
    • 如何控制只有一個對象呢
      • 怎么設(shè)計這個類的內(nèi)部對象
      • 外部怎么訪問
    • 單例模式的主要有以下角色
  • 單例模式的實現(xiàn)
    • 餓漢式 1:靜態(tài)變量
    • 餓漢式 2:靜態(tài)代碼塊
    • 懶漢式 1:線程不安全
    • 懶漢式 2:線程安全—方法級上鎖
    • 懶漢式 3:雙重檢查鎖🚀
    • 懶漢式 4:靜態(tài)內(nèi)部類🚀
    • 餓漢式 3:枚舉🚀
  • 存在的問題
    • 序列化破壞單例
    • 反射破壞單例
  • JDK 源碼 - Runtime 類

單例模式(Singleton Pattern)是 Java 中最簡單的設(shè)計模式之一。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。
這種模式涉及到一個單一的類,該類負責創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

  • 所謂的單例模式保證某個類在程序中有且只有一個對象,類比現(xiàn)實生活中的地球類,只有一個地球?qū)ο?/li>

單例模式的結(jié)構(gòu)

如何控制只有一個對象呢

  • 我們創(chuàng)建一個對象是通過該類的構(gòu)造方法進行創(chuàng)建對象
  • 我們不能讓外部進行創(chuàng)建對象,不然誰都能創(chuàng)建對象,那么就保證不了單例,那么我們的構(gòu)造方法必須是private修飾,來控制對象的創(chuàng)建,也就是私有的構(gòu)造方法
  • 外部不能創(chuàng)建對象,那么這個創(chuàng)建唯一的對象的任務(wù)也就會在我們單例類來進行實現(xiàn)

怎么設(shè)計這個類的內(nèi)部對象

  • 首先我們知道在外部是創(chuàng)建不了對象的,所以這個對象的類型肯定不能是成員的,必須是靜態(tài)的,通過類調(diào)用
  • 因為成員變量的屬性是通過我們的對象進行賦值,我們只有一個對象,如果是成員變量,就先要有對象才能賦值,而賦值了才有那個唯一的對象,就出現(xiàn)了死循環(huán)

外部怎么訪問

  • 一般屬性我們用private進行修飾,為了實現(xiàn)其封裝性
  • 直接通過公開的方法獲取這個唯一的對象

單例模式的主要有以下角色

  • 單例類。只能創(chuàng)建一個實例的類
  • 訪問類。使用單例類

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

單例設(shè)計模式分類兩種:

  • 餓漢式:類加載就會導(dǎo)致該單實例對象被創(chuàng)建
  • 懶漢式:類加載不會導(dǎo)致該單實例對象被創(chuàng)建,而是首次使用該對象時才會創(chuàng)建

餓漢式 1:靜態(tài)變量

public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建private static Singleton singleton=new Singleton();//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static Singleton getSingleton() {return singleton;}
}
  • 因為singleton是類成員變量,在我 Singleton類加載過程中的初始化過程中進行創(chuàng)建對象賦值,因為只會執(zhí)行一次,所以是天然的線程安全
  • 缺點:singleton 對象是隨著類的加載而創(chuàng)建的,如果該對象很大,卻一直沒有使用就會造成內(nèi)存的浪費

餓漢式 2:靜態(tài)代碼塊

該方式在成員位置聲明 Singleton 類型的靜態(tài)變量,而對象的創(chuàng)建是在靜態(tài)代碼塊中,也是隨著類的加載而創(chuàng)建。

public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建private static Singleton singleton;static {singleton=new Singleton();}//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static Singleton getSingleton() {return singleton;}
}

該方式和餓漢式的方式 1 基本一樣,所以該方式也存在內(nèi)存浪費問題。

懶漢式 1:線程不安全

該方式在成員位置聲明 Singleton 類型的靜態(tài)變量,并沒有進行對象的賦值操作,那么什么時候賦值的呢?

當調(diào)用 getInstance() 方法獲取 Singleton 類的對象的時候才創(chuàng)建 Singleton 類的對象,這樣就實現(xiàn)了懶加載效果。

public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建private static Singleton singleton;//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static Singleton getSingleton(){if(singleton==null){singleton=new Singleton();}return singleton;}
}

測試

public class Client {public static void main(String[] args) {Thread thread1=new Thread(()->{System.out.println(Singleton.getSingleton());});thread1.start();System.out.println(Singleton.getSingleton());}
}
//com.lsc.itheima.pattern.singleton.demo3.Singleton@3d075dc0
//com.lsc.itheima.pattern.singleton.demo3.Singleton@6b047ec
  • 發(fā)現(xiàn)不是同一個對象,沒有實現(xiàn)其單例的效果
  • 為什么不是線程安全的
    • 比如我們的thread1線程調(diào)用了getSingleton,進行if(singleton==null)判斷,進入了判斷體
    • 然后我們的main線程搶占了CPU,進行運行,進行if(singleton==null)判斷,因為thread1線程并沒有進行創(chuàng)建對象,也進入了判斷體
    • 故兩個線程各自創(chuàng)建了對應(yīng)的對象

懶漢式 2:線程安全—方法級上鎖

在懶漢式 1 的基礎(chǔ)上,使用 synchronized 關(guān)鍵字對getSingleton這個方法進行加鎖

public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建private static Singleton singleton;//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static synchronized Singleton getSingleton(){if(singleton==null){singleton=new Singleton();}return singleton;}
}
  • 但是該方法的執(zhí)行效率特別低。
    • 懶漢模式中加鎖的問題,對于 getSingleton 方法來說,絕大部分的操作都是讀操作,讀操作是線程安全的,所以我們沒必讓每個線程必須持有鎖才能調(diào)用該方法,我們需要調(diào)整加鎖的時機。由此也產(chǎn)生了一種新的實現(xiàn)模式:雙重檢查鎖模式
  • 注意:其實只有在初始化singleton的時候才會出現(xiàn)線程安全問題,一旦初始化完成就不存在了。

懶漢式 3:雙重檢查鎖🚀

public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建private static Singleton singleton;//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static  Singleton getSingleton(){//第一次判斷,如果singleton不為null,不進入搶鎖階段,直接返回實例if(singleton==null){synchronized (Singleton.class) {// 第二次判斷,搶占到鎖以后再次判斷if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

雙重檢查鎖模式是一種非常好的單例實現(xiàn)模式,解決了單例、性能、線程安全問題,上面的雙重檢測鎖模式看上去完美無缺,其實是存在問題,在多線程的情況下,可能會出現(xiàn)空指針問題,出現(xiàn)問題的原因是JVM在實例化對象的時候會進行優(yōu)化和指令重排序操作。

  • 要解決雙重檢查鎖模式帶來空指針異常的問題,只需要使用 volatile 關(guān)鍵字, volatile 關(guān)鍵字可以保證可見性和有序性。
  • 使用volatile關(guān)鍵字保證單例對象初始化不會被中斷,保證其他線程獲得的對象一定是初始化完成的對象
    • 比如現(xiàn)在t1線程執(zhí)行到了初始化的實例對象,正在執(zhí)行new操作,還沒完全結(jié)束(但是LazySingleTon!=null),然后t2線程執(zhí)行到了判斷唯一的對象是否為空,對于t2發(fā)現(xiàn)不為空,就直接返回了,但是返回的對象是沒有完全初始化的,所以需要加volatile,就相當加了一層內(nèi)存屏障,保證其他線程返回的對象必須等操作完全結(jié)束才能執(zhí)行return語句
public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建// 聲明Singleton類型的變量,使用volatile保證可見性和有序性private static volatile Singleton singleton;//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static  Singleton getSingleton(){// 第一次判斷,如果instance不為null,不需要搶占鎖,直接返回對象if(singleton==null){synchronized (Singleton.class) {// 第二次判斷,搶占到鎖以后再次判斷if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

懶漢式 4:靜態(tài)內(nèi)部類🚀

靜態(tài)內(nèi)部類單例模式中實例由內(nèi)部類創(chuàng)建,由于 JVM 在加載外部類的過程中,是不會加載靜態(tài)內(nèi)部類的,只有內(nèi)部類的屬性/方法被調(diào)用時才會被加載,并初始化其靜態(tài)屬性。靜態(tài)屬性由于被 static 修飾,保證只被實例化一次,并且嚴格保證實例化順序。

public class Singleton {//2私有化構(gòu)造方法private Singleton(){}// 定義一個靜態(tài)內(nèi)部類private static class SingletonHolder {// 在內(nèi)部類中聲明并初始化外部類的對象private static final Singleton singleton = new Singleton();}// 提供公共的訪問方式public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

第一次加載 Singleton 類時不會去初始化 singleton,只有第一次調(diào)用 getInstance(),虛擬機加載 SingletonHolder 類并初始化 singleton,這樣不僅能確保線程安全,也能保證 Singleton 類的唯一性。

靜態(tài)內(nèi)部類單例模式是一種優(yōu)秀的單例模式,是開源項目中比較常用的一種單例模式。在沒有加任何鎖的情況下,保證了多線程下的安全,并且沒有任何性能影響和空間的浪費。

餓漢式 3:枚舉🚀

首先,枚舉方式是餓漢式單例模式,如果不考慮浪費內(nèi)存空間的問題,這是極力推薦的單例實現(xiàn)模式。

因為枚舉類型是線程安全的,并且只會裝載一次,設(shè)計者充分的利用了枚舉的這個特性來實現(xiàn)單例模式。

枚舉的寫法非常簡單,而且枚舉方式是所用單例實現(xiàn)中唯一一種不會被破壞的單例實現(xiàn)模式。

public class SingleTon {/*** 餓漢式:枚舉實現(xiàn)*/public enum Singleton {INSTANCE}
}

存在的問題

有兩種方式可以使上面定義的單例類可以創(chuàng)建多個對象(枚舉方式除外),分別是序列化反射。

枚舉方式是利用了 Java 特性實現(xiàn)的單例模式,不會被破壞,其他實現(xiàn)方式都有可能會被破壞

序列化破壞單例

問題演示:下面代碼運行結(jié)果是false,表明序列化和反序列化破壞了單例設(shè)計模式。

public class Client {public static void main(String[] args) throws IOException, ClassNotFoundException {writeObject2File();Singleton s1 = readObjectFormFile();Singleton s2 = readObjectFormFile();
//        System.out.println(s1 == s2); // false}//從文件讀取數(shù)據(jù)public static  Singleton readObjectFormFile() throws IOException, ClassNotFoundException {//創(chuàng)建對象輸入流對象ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\a.txt"));//2.讀取對象Singleton singleton =(Singleton) objectInputStream.readObject();//3釋放資源objectInputStream.close();return singleton;}//向文件寫數(shù)據(jù)public static void writeObject2File() throws IOException {//1獲取Singleton對象Singleton singleton = Singleton.getSingleton();//創(chuàng)建對象輸出流對象ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\a.txt"));// 3.寫對象objectOutputStream.writeObject(singleton);// 4.釋放資源objectOutputStream.close();}
}

解決方案:在 Singleton 類中添加readResolve()方法。

在反序列化時被反射調(diào)用,如果定義了這個方法,就返回這個方法的值,如果沒有定義,則返回新 new 出來的對象。

/*** 雙重加鎖方式(解決序列化破解單例模式)*/
public class Singleton implements Serializable {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建 聲明Singleton類型的變量,使用volatile保證可見性和有序性private static volatile Singleton singleton;//2私有化構(gòu)造方法private Singleton(){}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static  Singleton getSingleton(){// 第一次判斷,如果instance不為null,不需要搶占鎖,直接返回對象if(singleton==null){synchronized (Singleton.class) {// 第二次判斷,搶占到鎖以后再次判斷if (singleton == null) {singleton = new Singleton();}}}return singleton;}/*** 下面是為了解決序列化反序列化破解單例模式* 當進行反序列化時,會自動調(diào)用該方法,將該方法的返回值直接返回*/private Object readResolve() {return getSingleton();}}

反射破壞單例

public class Client {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {//1 獲取Singleton的字節(jié)碼對象Class<Singleton> singletonClass = Singleton.class;//2獲取無參構(gòu)造方法對象Constructor<Singleton> declaredConstructor = singletonClass.getDeclaredConstructor();//3取消訪問檢查declaredConstructor.setAccessible(true);// 4.創(chuàng)建Singleton對象Singleton s1 = (Singleton) declaredConstructor.newInstance();Singleton s2 = (Singleton) declaredConstructor.newInstance();System.out.println(s1 == s2); // false}
}

解決方案:當通過反射方式調(diào)用構(gòu)造方法進行創(chuàng)建時,直接拋異常

public class Singleton {//1定義靜態(tài)成員變量,在類加載時創(chuàng)建 聲明Singleton類型的變量,使用volatile保證可見性和有序性private static volatile Singleton singleton;private static boolean flag = false;//2私有化構(gòu)造方法// 私有構(gòu)造方法private Singleton() {synchronized (Singleton.class) {// 如果是true,說明非第一次訪問,直接拋一個異常,如果是false,說明第一次訪問if (flag) {throw new RuntimeException("不能創(chuàng)建多個對象");}flag = true;}}// 3.提供一個公共的訪問方式,讓外界獲取該對象public static  Singleton getSingleton(){// 第一次判斷,如果instance不為null,不需要搶占鎖,直接返回對象if(singleton==null){synchronized (Singleton.class) {// 第二次判斷,搶占到鎖以后再次判斷if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

JDK 源碼 - Runtime 類

Runtime 類使用的就是單例設(shè)計模式。

源碼查看:下面是 Runtime 類的源碼,是靜態(tài)變量方式的餓漢單例模式。

public class Runtime {private static Runtime currentRuntime = new Runtime();/*** Returns the runtime object associated with the current Java application.* Most of the methods of class <code>Runtime</code> are instance* methods and must be invoked with respect to the current runtime object.** @return  the <code>Runtime</code> object associated with the current*          Java application.*/public static Runtime getRuntime() {return currentRuntime;}/** Don't let anyone else instantiate this class */private Runtime() {}...
}
/***  RuntimeDemo*/
public class RuntimeDemo {public static void main(String[] args) throws IOException {// 獲取Runtime類的對象Runtime runtime = Runtime.getRuntime();// 調(diào)用runtime的方法exec,參數(shù)要的是一個命令Process process = runtime.exec("ifconfig");// 調(diào)用process對象的獲取輸入流的方法InputStream is =  process.getInputStream();byte[] arr = new byte[1024 * 1024 * 100];// 讀取數(shù)據(jù)int len = is.read(arr); // 返回讀到的字節(jié)的個數(shù)// 將字節(jié)數(shù)組轉(zhuǎn)換為字符串輸出到控制臺System.out.println(new String(arr, 0, len, "GBK"));}
}
http://www.risenshineclean.com/news/50813.html

相關(guān)文章:

  • 律師網(wǎng)站建設(shè)哪家好怎么查找關(guān)鍵詞排名
  • 黑色網(wǎng)站源碼seo比較好的優(yōu)化方法
  • wordpress自定義鏈接怎么配置外貿(mào)seo是什么意思
  • 新疆電子商務(wù)平臺網(wǎng)站開發(fā)百度掃一掃識別圖片在線
  • 做網(wǎng)站需要招什么職位建個網(wǎng)站需要多少錢
  • 肇慶網(wǎng)站seo河北百度代理公司
  • 永年網(wǎng)站建設(shè)競價推廣開戶
  • wordpress為什么在自定義結(jié)構(gòu)的時候總是出現(xiàn)斜杠呢sem 優(yōu)化價格
  • 成都網(wǎng)站制作成都網(wǎng)站制作項目外包平臺
  • 招標網(wǎng)站的服務(wù)費怎么做分錄免費網(wǎng)站統(tǒng)計工具
  • 網(wǎng)站推廣的方法百度seo營銷推廣
  • php網(wǎng)站開發(fā)零基礎(chǔ)教程seo自學
  • wordpress管理員怎么進入后臺開源seo軟件
  • 廣州知名網(wǎng)站建設(shè)哪家好市場調(diào)研的方法
  • 養(yǎng)老網(wǎng)站建設(shè)方案上海企業(yè)seo
  • 浪網(wǎng)站制作電商網(wǎng)站建設(shè)定制
  • 四川城鄉(xiāng)和住房建設(shè)廳網(wǎng)站首頁競價推廣論壇
  • 計算機程序設(shè)計網(wǎng)站開發(fā)小程序怎么開發(fā)
  • 溫嶺網(wǎng)站開發(fā)友鏈交換有什么作用
  • 分析網(wǎng)站建設(shè)前期的seo準備工作推廣app拿返傭的平臺
  • wordpress設(shè)置標題大小嘉興新站seo外包
  • wordpress中文客服側(cè)邊欄qq上海優(yōu)化公司排行榜
  • 區(qū)塊鏈開發(fā)與應(yīng)用seo網(wǎng)站排名查詢
  • 上傳文件的網(wǎng)站sem工具是什么
  • 網(wǎng)站樣板谷歌搜索引擎google
  • spring可以做多大的網(wǎng)站找個網(wǎng)站
  • 沈陽網(wǎng)站開發(fā)技術(shù)公司web前端培訓(xùn)費用大概多少
  • 碑林網(wǎng)站制作什么是搜索引擎銷售
  • 東莞常平做網(wǎng)站百度指數(shù)如何分析數(shù)據(jù)
  • 廣西玉林建設(shè)廳官方網(wǎng)站代運營公司哪家好一些