圖文結(jié)合講解Java單例模式
PS:首先我們要先知道什么是單例,為什么要用單例,用的好處是什么等問題來看。
1:java中單例模式是一種常見的設(shè)計模式,單例模式的寫法有好幾種,這里主要介紹兩種:懶漢式單例、餓漢式單例
單例模式有以下特點:
1、單例類只能有一個實例。
2、單例類必須自己創(chuàng)建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。
單例模式確保某個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。在計算機系統(tǒng)中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅(qū)動程序?qū)ο蟪1辉O(shè)計成單例。這些應(yīng)用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業(yè)同時輸出到打印機中。每臺計算機可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調(diào)用??傊x擇單例模式就是為了避免不一致狀態(tài),避免政出多頭。
2:懶漢式
先把單例類寫出來
public class SingletonTest {
//懶漢式單例類.在第一次調(diào)用的時候?qū)嵗约?
private SingletonTest() {}
private static SingletonTest single=null;
//靜態(tài)工廠方法
public static SingletonTest getInstance() {
if (single == null) {
single = new SingletonTest();
System.out.println("創(chuàng)建一次");
}
return single;
}
public void show(){
System.out.println("我是show");
}
}
這里直接上代碼,代碼中有詳解
public class SingletonTest2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//故意寫獲取兩次,創(chuàng)建兩個對象
SingletonTest singleton=SingletonTest.getInstance();
SingletonTest singleton2=SingletonTest.getInstance();
//Singleton對象只創(chuàng)建一次,但是寫兩次還是可以的,而且方法都是可以調(diào)用的,但是看下面
singleton.show();
singleton2.show();
//兩個對象的表現(xiàn)形式一樣
if(singleton == singleton2){
System.out.println("該對象的字符串表示形式:");
System.out.println("singleton :"+singleton.toString());
System.out.println("singleton2:"+singleton2.toString());
}

由上面的圖可以看出就算多創(chuàng)建幾個對象,在底部也是只有一個singleton對象實例,而且創(chuàng)建出來的對象的字符串表現(xiàn)形式也是一樣的,有的人肯定有疑問,那平常兩個對象是什么樣子的呢,我下面給你解釋說明,在這之前我寫說一下這個懶漢式需要注意的地方,它是線程不安全的,并發(fā)環(huán)境下很可能出現(xiàn)多個Singleton實例,有很多方法可以解決,比如說同步鎖,靜態(tài)內(nèi)部類等,這里主要說靜態(tài)內(nèi)部類,這個比較好點,
public class Singleton3 {
private static class SingletonHolder {
private static final Singleton3 INSTANCE = new Singleton3();
}
private Singleton3 (){}
public static final Singleton3 getInstance() {
System.out.println("singleton創(chuàng)建");
return SingletonHolder.INSTANCE;
}
}
調(diào)用:
Singleton3 singleton3=Singleton3.getInstance();
Singleton3 singleton4=Singleton3.getInstance();
if(singleton3 == singleton4){
System.out.println("該對象的字符串表示形式:");
System.out.println("singleton3:"+singleton3.toString());
System.out.println("singleton4:"+singleton4.toString());
}
結(jié)果圖:

這里我也是創(chuàng)建了兩個對象來說明,神奇的是打印了兩次singleton創(chuàng)建,這難道是又創(chuàng)建成功了的對象嗎?答案是:雖然打印了兩次,對象名也有兩個,但是該對象的字符串表示形式還是一樣的,而且大家都知道static的用法,就是在類被加載的同時該singleton對象就已經(jīng)被創(chuàng)建,后期不會再被創(chuàng)建,就算后期自己又調(diào)用了getInstance()方法,但底層還是公用的一個Singleton對象.
同樣,我寫了一個普通的類,來同時創(chuàng)建兩個對象,并且打印他們的toString()方法,如下:
QuBie qb1=new QuBie();
QuBie qb2=new QuBie();
if(qb1 == qb2){
System.out.println("該對象的字符串表示形式:");
System.out.println("singleton3:"+qb1.toString());
System.out.println("singleton4:"+qb2.toString());
}else{
System.out.println("該對象的字符串表示形式:");
System.out.println("singleton3:"+qb1.toString());
System.out.println("singleton4:"+qb2.toString());
}

由此可看出來對象的字符串表示形式是不一樣的
3:餓漢式單例
餓漢式單例類.在類初始化時,已經(jīng)自行實例化
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//靜態(tài)工廠方法
public static Singleton1 getInstance() {
return single;
}
}
因為這本身就是static修飾的方法,所以是在類加載的時候被創(chuàng)建,后期不會再改變,所以線程是安全的。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解spring-cloud與netflixEureka整合(注冊中心)
這篇文章主要介紹了詳解spring-cloud與netflixEureka整合(注冊中心),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
聊聊springboot靜態(tài)資源加載的規(guī)則
這篇文章主要介紹了springboot靜態(tài)資源加載的規(guī)則,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
Java Flink與kafka實現(xiàn)實時告警功能過程
這篇文章主要介紹了Java Flink與kafka實現(xiàn)實時告警功能,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01
詳細(xì)總結(jié)各種排序算法(Java實現(xiàn))
下面小編就為大家?guī)硪黄敿?xì)總結(jié)各種排序算法(Java實現(xiàn))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
Java中的main方法調(diào)用非靜態(tài)方法處理
這篇文章主要介紹了Java中的main方法調(diào)用非靜態(tài)方法處理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

