ps:首先我們要先知道什么是單例,為什么要用單例,用的好處是什么等問題來看。
1:java中單例模式是一種常見的設計模式,單例模式的寫法有好幾種,這里主要介紹兩種:懶漢式單例、餓漢式單例
單例模式有以下特點:
1、單例類只能有一個實例。
2、單例類必須自己創建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。
單例模式確保某個類只有一個實例,而且自行實例化并向整個系統提供這個實例。在計算機系統中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個printer spooler,以避免兩個打印作業同時輸出到打印機中。每臺計算機可以有若干通信端口,系統應當集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用。總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。
2:懶漢式
先把單例類寫出來
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class singletontest { //懶漢式單例類.在第一次調用的時候實例化自己 private singletontest() {} private static singletontest single= null ; //靜態工廠方法 public static singletontest getinstance() { if (single == null ) { single = new singletontest(); system.out.println( "創建一次" ); } return single; } public void show(){ system.out.println( "我是show" ); } } |
這里直接上代碼,代碼中有詳解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class singletontest2 { public static void main(string[] args) { // todo auto-generated method stub //故意寫獲取兩次,創建兩個對象 singletontest singleton=singletontest.getinstance(); singletontest singleton2=singletontest.getinstance(); //singleton對象只創建一次,但是寫兩次還是可以的,而且方法都是可以調用的,但是看下面 singleton.show(); singleton2.show(); //兩個對象的表現形式一樣 if (singleton == singleton2){ system.out.println( "該對象的字符串表示形式:" ); system.out.println( "singleton :" +singleton.tostring()); system.out.println( "singleton2:" +singleton2.tostring()); } |
由上面的圖可以看出就算多創建幾個對象,在底部也是只有一個singleton對象實例,而且創建出來的對象的字符串表現形式也是一樣的,有的人肯定有疑問,那平常兩個對象是什么樣子的呢,我下面給你解釋說明,在這之前我寫說一下這個懶漢式需要注意的地方,它是線程不安全的,并發環境下很可能出現多個singleton實例,有很多方法可以解決,比如說同步鎖,靜態內部類等,這里主要說靜態內部類,這個比較好點,
1
2
3
4
5
6
7
8
9
10
|
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創建" ); return singletonholder.instance; } } |
調用:
1
2
3
4
5
6
7
|
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()); } |
結果圖:
這里我也是創建了兩個對象來說明,神奇的是打印了兩次singleton創建,這難道是又創建成功了的對象嗎?答案是:雖然打印了兩次,對象名也有兩個,但是該對象的字符串表示形式還是一樣的,而且大家都知道static的用法,就是在類被加載的同時該singleton對象就已經被創建,后期不會再被創建,就算后期自己又調用了getinstance()方法,但底層還是公用的一個singleton對象.
同樣,我寫了一個普通的類,來同時創建兩個對象,并且打印他們的tostring()方法,如下:
1
2
3
4
5
6
7
8
9
10
11
|
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:餓漢式單例
餓漢式單例類.在類初始化時,已經自行實例化
1
2
3
4
5
6
7
8
|
public class singleton1 { private singleton1() {} private static final singleton1 single = new singleton1(); //靜態工廠方法 public static singleton1 getinstance() { return single; } } |
因為這本身就是static修飾的方法,所以是在類加載的時候被創建,后期不會再改變,所以線程是安全的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/jjhahage/article/details/78277105