如何實(shí)現(xiàn)Singleton模式,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
我們提供的服務(wù)有:網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、博樂(lè)ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的博樂(lè)網(wǎng)站制作公司
設(shè)計(jì)一個(gè)類,我們只能生成該類的一個(gè)實(shí)例
私有構(gòu)造方法
靜態(tài)方法獲取實(shí)例
如果需要考慮內(nèi)存,使用到時(shí)才創(chuàng)建實(shí)例對(duì)象(餓漢),不使用時(shí)就不創(chuàng)建實(shí)例(懶漢,懶加載)。
如果需要考慮線程安全,就要確保獲取實(shí)例是同步的,避免創(chuàng)建多個(gè)實(shí)例。
[x] 1. 單線程(懶漢式、餓漢式)
[x] 2. 多線程工作效率不高(加鎖獲取實(shí)例的方法)
[x] 3. 加同步鎖前后兩次判斷實(shí)例是否已存在
[x] 4. 利用靜態(tài)初始化創(chuàng)建實(shí)例(推薦,線程安全,會(huì)占用一部分內(nèi)存)
[x] 5. 利用靜態(tài)內(nèi)部類實(shí)現(xiàn)按需創(chuàng)建實(shí)例(最推薦,線程安全,效率高,聰明的你應(yīng)該可以明白的)
package cn.jast.java.offer.singleton; /** * 簡(jiǎn)單餓漢單例 * */ public class SimpleHungerSingleton { private static SimpleHungerSingleton simpleSingleton; private SimpleHungerSingleton(){ simpleSingleton = new SimpleHungerSingleton(); } public static SimpleHungerSingleton getInstance(){ return simpleSingleton; } }
package cn.jast.java.offer.singleton; /** * 簡(jiǎn)單懶漢單例 * */ public class SimpleLazySingleton { private static SimpleLazySingleton simpleSingleton; private SimpleLazySingleton(){ } public static SimpleLazySingleton getInstance(){ if(simpleSingleton == null){ simpleSingleton = new SimpleLazySingleton(); } return simpleSingleton; } }
/** * 測(cè)試簡(jiǎn)單單例的線程安全 */ public static void testSimpleLazySingleton(){ SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ SimpleLazySingleton simpleLazySingleton = SimpleLazySingleton.getInstance(); singletonSet.add(simpleLazySingleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } }
輸出:
簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下: [cn.jast.java.offer.singleton.SimpleLazySingleton@2b9283d, cn.jast.java.offer.singleton.SimpleLazySingleton@72fba635]
package cn.jast.java.offer.singleton; public class Synchronized1Singleton { private static Synchronized1Singleton instance; private Synchronized1Singleton(){ } /** * 每次獲取對(duì)象時(shí)都加鎖來(lái)確保創(chuàng)建對(duì)象 * @return */ public static synchronized Synchronized1Singleton getInstance(){ if(instance == null){ instance = new Synchronized1Singleton(); } return instance; } }
測(cè)試:
public static void testSynchronized1Singleton(){ long startTime = System.currentTimeMillis(); SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized1Singleton singleton = Synchronized1Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("執(zhí)行時(shí)間:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } }
輸出:
執(zhí)行時(shí)間:72 ms(注:一個(gè)樣例)
package cn.jast.java.offer.singleton; public class Synchronized2Singleton { private static Synchronized2Singleton instance; private Synchronized2Singleton(){ } public static Synchronized2Singleton getInstance(){ if(instance == null){ synchronized (Synchronized2Singleton.class){ if(instance==null){ instance = new Synchronized2Singleton(); } } } return instance; } }
package cn.jast.java.offer.singleton; /** * 推薦 */ public class StaticInitializeSingleton { private static StaticInitializeSingleton instance ; static{ instance = new StaticInitializeSingleton(); } private StaticInitializeSingleton(){ } public static StaticInitializeSingleton getInstance(){ return instance; } }
package cn.jast.java.offer.singleton; /** * 推薦 */ public class StaticInnerClassSingleton { private StaticInnerClassSingleton(){ } public static StaticInnerClassSingleton getInstance(){ return Inner.instance; } private static class Inner{ private static final StaticInnerClassSingleton instance = new StaticInnerClassSingleton(); } }
package cn.jast.java.offer.singleton; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { // testSimpleLazySingleton(); testSynchronized1Singleton(); // testSynchronized2Singleton(); // testStaticInitializeSingleton(); // testNestedClassSingleton(); } /** * 測(cè)試簡(jiǎn)單單例的線程安全 */ public static void testSimpleLazySingleton(){ SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ SimpleLazySingleton simpleLazySingleton = SimpleLazySingleton.getInstance(); singletonSet.add(simpleLazySingleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } } /** * 測(cè)試線程安全的單例模式實(shí)現(xiàn) */ public static void testSynchronized1Singleton(){ long startTime = System.currentTimeMillis(); Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized1Singleton singleton = Synchronized1Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("執(zhí)行時(shí)間:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } } /** * Synchronized2Singleton 的效率比 Synchronized1Singleton高幾倍甚至幾十倍以上 */ public static void testSynchronized2Singleton(){ long startTime = System.currentTimeMillis(); Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized2Singleton singleton = Synchronized2Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("執(zhí)行時(shí)間:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } } /** * */ public static void testStaticInitializeSingleton(){ Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized2Singleton singleton = Synchronized2Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } } public static void testNestedClassSingleton(){ Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ StaticInnerClassSingleton singleton = StaticInnerClassSingleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("簡(jiǎn)單單例存在創(chuàng)建多個(gè)實(shí)例對(duì)象,實(shí)例如下:"); System.out.println(singletonSet); } break; } } } }
問(wèn):?jiǎn)卫J将@取實(shí)例的方法為什么是靜態(tài)方法? 答:因?yàn)闃?gòu)造方法是私有的,無(wú)法通過(guò)new創(chuàng)建實(shí)例,那只能通過(guò)類方法獲取實(shí)例。那通過(guò)反射是否可以創(chuàng)建實(shí)例呢?
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。