轉自:
http://www.java265.com/JavaCourse/202109/1153.html
下文是筆者撰寫的單例模式實作的八種方式,如下所示:
單例模式的簡介
我們將一個類在當前行程中只有一個實體的這種模式,稱之為“單例模式”
那么Java代碼如何實作一個單例模式呢?下文將一一到來,如下所示:
單例模式的注意事項: 1.單例模式在一個行程中只有一個實體 2.單例類通常由自己創建自身的實體 3.單例類給其他物件提供的都是同一個實體
測驗代碼
package com.java265.Singleton; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("------單例模式-----"); //創建100個執行緒進行測驗 for(int i=0;i<100;i++) { new Thread(()->{ System.out.println(Single01.getInstance()); }).start(); } } }
單例實作模式1
餓漢式單例模式:
直接使用一個靜態變數,在JVM加載類時,生成一個單例實體 如下
package com.java265.Singleton; public class Single01 { private static final Single01 INSTANCE = new Single01(); private Single01() {} public static Single01 getInstance () { return INSTANCE; } }
使用static靜態代碼塊生成一個單例類
package com.java265.Singleton; public class Single02 { private static final Single02 INSTANCE; static { INSTANCE = new Single02(); } private Single02() {} public static Single02 getInstance() { return INSTANCE; } public void t() { System.out.println("Single02 t方法" + ""); } }
使用判斷的方式,創建單例模式,
但是此處不是一個執行緒安全的創建方式
package com.java265.Singleton; /* * 這是一個執行緒不安全的創建單例模式的方式 * 這是一個懶漢式的創建單例模式的方式 * */ public class Single03 { private static Single03 INSTANCE; private Single03() { } public static Single03 getInstance() { if(INSTANCE ==null) { // 多個執行緒都會被卡在此處, // 當sleep運行完畢后,多個執行緒會同時創建實體,此處的代碼是產生執行緒不安全的根源 try { Thread.sleep(100); }catch(InterruptedException e) { } INSTANCE = new Single03(); } return INSTANCE; } }
使用 synchronized為方法加上鎖,使其執行緒安全
package com.java265.Singleton; public class Single04 { private static volatile Single04 INSTANCE; private Single04() { } /* * 懶漢式生成單例實體 此處使用 synchronized 安全鎖 */ public static synchronized Single04 getInstance() { if(INSTANCE ==null) { try { Thread.sleep(100); }catch(InterruptedException e) { } INSTANCE = new Single04(); } return INSTANCE; } }
減少鎖粒度,將synchronized關鍵字直接加在方法內部具體的位置上
package com.java265.Singleton; public class Single05 { private static Single05 INSTANCE; private Single05() { } public static Single05 getInstance() { if(INSTANCE ==null) { /* * 將鎖直接加到方法體里面 此時出現了一個新的問題 當所有的執行緒都堵塞在此處,也會創建多個實體 */ synchronized(Single05.class) { try { Thread.sleep(100); }catch(InterruptedException e) { } INSTANCE = new Single05(); } } return INSTANCE; } }
將synchronized鎖放入在方法體中,同時使用雙重檢查,避免創建多個實體
package com.java265.Singleton; public class Single06 { private static Single06 INSTANCE; private Single06() { } public static Single06 getInstance() { if(INSTANCE ==null) { synchronized(Single06.class) { try { Thread.sleep(100); }catch(InterruptedException e) { } if(INSTANCE == null) { INSTANCE = new Single06(); } } } return INSTANCE; } }
使用靜態內部類的方式創建一個單例物件
此方式主要借助JVM加載類時,內部類不會被加載
當我們使用內部類的時,才會被加載,此時由JVM保證靜態內部類的唯一性
package com.java265.Singleton; /* * 采用內部類的方式實作一個單例模式 * */ public class Single07 { private Single07() { } private static class Single07Holder { private final static Single07 INSTANCE = new Single07(); } public static Single07 getInstance() { return Single07Holder.INSTANCE; } }
使用列舉創建一個靜態內部類
package com.java265.Singleton; /* * 采用列舉實作一個單例模式 * */ public enum Single08 { INSTANCE; public static Single08 getInstance() { return INSTANCE; } }
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/472863.html
標籤:Java
下一篇:php回圈陳述句
