Java中常用的設(shè)計(jì)模式之單例模式詳解
注意
1、單例類只能有一個(gè)實(shí)例。
2、單例類必須自己創(chuàng)建自己的唯一實(shí)例。
3、單例類必須給所有其他對象提供這一實(shí)例。
優(yōu)點(diǎn)
1.在內(nèi)存里只有一個(gè)實(shí)例,減少了內(nèi)存的開銷,尤其是頻繁的創(chuàng)建和銷毀實(shí)例(比如管理學(xué)院首頁頁面緩存)。
2.避免對資源的多重占用(比如寫文件操作)。
缺點(diǎn)
1.沒有接口,不能繼承,與單一職責(zé)原則沖突,一個(gè)類應(yīng)該只關(guān)心內(nèi)部邏輯,而不關(guān)心外面怎么樣來實(shí)例化。
使用場景
1.要求生產(chǎn)唯一序列號。
2.WEB 中的計(jì)數(shù)器,不用每次刷新都在數(shù)據(jù)庫里加一次,用單例先緩存起來。
3.創(chuàng)建的一個(gè)對象需要消耗的資源過多,比如 I/O 與數(shù)據(jù)庫的連接等。
一、實(shí)現(xiàn)方式
package com.asurplus.common.singleton.style1;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
@Slf4j
public class ResUtils {
private volatile static ResUtils instance = null;
/**
* 私有的構(gòu)造方法
*/
private ResUtils() {
}
/**
* 提供獲取實(shí)例的方法
*
* @return
*/
public static ResUtils getInstance() {
// 為空才創(chuàng)建
if (Objects.isNull(instance)) {
// 避免并發(fā)操作時(shí)
synchronized (ResUtils.class) {
// 為空才創(chuàng)建
if (Objects.isNull(instance)) {
// 創(chuàng)建新對象
instance = new ResUtils();
log.info("創(chuàng)建了對象");
}
}
}
return instance;
}
}
我們將其構(gòu)造方法私有化,從而外部無法創(chuàng)建實(shí)例,并且我們提供了獲取唯一實(shí)例的方法,這樣我們就能從外部得到該實(shí)例。
二、實(shí)現(xiàn)方式
package com.asurplus.common.singleton.style2;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ResUtils2 {
/**
* 靜態(tài)內(nèi)部類
*/
private static class ResUtils2Holder {
private static ResUtils2 instance = new ResUtils2();
}
/**
* 提供獲取實(shí)例的方法
*
* @return
*/
public static ResUtils2 getInstance() {
return ResUtils2Holder.instance;
}
}
我們使用靜態(tài)內(nèi)部類的方法創(chuàng)建實(shí)例,因?yàn)?JVM 只會加載一次的原理,所以最終只會創(chuàng)建一個(gè)實(shí)例,并且提供了獲取實(shí)例的方法,這樣我們就能從外部得到該實(shí)例。
三、測試
package com.asurplus.common.singleton;
import com.asurplus.common.singleton.style1.ResUtils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 單例模式
*/
public class TestMain {
public static void main(String[] args) {
// 創(chuàng)建線程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executorService.execute(ResUtils::getInstance);
}
executorService.shutdown();
}
}
輸出結(jié)果

可以看出,我們獲取了 100 次實(shí)例,只創(chuàng)建了一個(gè)實(shí)例,從而實(shí)現(xiàn)了我們的單例模式。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Springboot?jpa使用sum()函數(shù)返回結(jié)果如何被接收
這篇文章主要介紹了Springboot?jpa使用sum()函數(shù)返回結(jié)果如何接收,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
springboot 整合druid數(shù)據(jù)庫密碼加密功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了springboot 整合druid數(shù)據(jù)庫密碼加密功能的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
java實(shí)現(xiàn)即時(shí)通信的完整步驟分享
這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)即時(shí)通信的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
JAVA Spring Boot 自動配置實(shí)現(xiàn)原理詳解
這篇文章主要介紹了詳解SpringBoot自動配置原理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-09-09
java?-jar命令及SpringBoot通過java?-jav啟動項(xiàng)目的過程
本篇文章將為大家講述關(guān)于 SpringBoot 項(xiàng)目工程完成后,是如何通過 java-jar 命令來啟動的,以及介紹 java-jar 命令的詳細(xì)內(nèi)容,對SpringBoot java?-jav啟動過程感興趣的朋友跟隨小編一起看看吧2023-05-05

