單例模式的介紹
單例對象(Singleton)是一種常用的設計模式。在實際使用中,單例對象能保證在一個JVM中,該對象只存在一個實例存在。
優點
1、減少系統開銷,提高系統性能
2、省去了new操作符,降低了系統內存的使用頻率,減輕GC壓力
3、避免對共享資源的多重占用
缺點
1、不適應用多變的對象
2、擴展困難
3、單例類的職責過重,在一定程度上違背了“單一職責原則”。
Synchronized
Synchronized示例
介紹單例模式前,我們現介紹一下Synchronized
示例如下:
建立一個內部類,并開啟子線程,如果實例該類,則自動執行test1()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class SynchronizedTest implements Runnable { private int count; public SynchronizedTest() { count = 0 ; } @Override public void run() { test1(); } private void test1() { synchronized ( this ) { for ( int i = 0 ; i < 5 ; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + count++); Thread.sleep( 500 ); } catch (InterruptedException e) { e.printStackTrace(); } } } } } |
構造一個SynchronizedTest 對象,傳入兩個線程對象
1
2
3
4
5
|
SynchronizedTest test = new SynchronizedTest(); Thread thread1 = new Thread(test, "test1" ); Thread thread2 = new Thread(test, "test2" ); thread1.start(); thread2.start(); |
由結果可知,當一個對象持有該代碼塊時,另一個線程訪問不到被鎖住的代碼塊,只要當前一線程執行完成,另一線程才能執行。
test1:0
test1:1
test1:2
test1:3
test1:4
test2:5
test2:6
test2:7
test2:8
test2:9
Synchronized與非Synchronized
建立一個內部類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
class SynchronizedTest implements Runnable { private int count; public SynchronizedTest() { count = 0 ; } @Override public void run() { if (Thread.currentThread().getName().equals( "S" )) { test1(); } else { test2(); } } public void test1() { synchronized ( this ) { for ( int i = 0 ; i < 5 ; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + (count++)); Thread.sleep( 500 ); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void test2() { for ( int i = 0 ; i < 5 ; i++) { try { System.out.println(Thread.currentThread().getName() + ":" + count); Thread.sleep( 500 ); } catch (InterruptedException e) { e.printStackTrace(); } } } } |
1
2
3
4
5
|
SynchronizedTest test = new SynchronizedTest(); Thread thread1 = new Thread(test, "S" ); Thread thread2 = new Thread(test, "N" ); thread1.start(); thread2.start(); |
由結果可知,一個線程訪問Synchronized修飾的代碼塊,另一個線程訪問非Synchronized代碼塊不受阻塞
S:0
N:1
N:2
S:1
N:2
S:2
S:3
N:4
S:4
N:5
Singleton
第一個示例
此示例實現了單例,但是如果放在多線程當中,將會漏洞百出
我們接著看下一個改良示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class Singleton { /* 持有私有靜態實例,防止被引用,此處賦值為null,目的是實現延遲加載 */ private static Singleton instance = null ; /* 私有構造方法,防止被實例化 */ private Singleton() { } /* 靜態工程方法,創建實例 */ public static Singleton getInstance() { if (instance == null ) { instance = new Singleton(); } return instance; } } |
第二個示例
根據第一個示例,我們進行改良,加上Synchronized。
但是每次調用getInstance()方法時,都會對對象上鎖,為了減少系統開銷,我們一般在第一次創建對象的時候加鎖,后面就不需要了
我們接著看下一個改良示例
1
2
3
4
5
6
|
public static synchronized Singleton getInstance() { if (instance == null ) { instance = new Singleton(); } return instance; } |
第三個示例
我們對上一個示例進行改良,只有在instance == null的時候,也就是第一次創建對象的時候,執行加鎖的區域。此種寫法解決了上一個示例遺留的問題,但是在Java指令中創建對象和賦值操作是分開進行的,也就是說instance = new Singleton();語句是分兩步執行的。但是JVM并不保證這兩個操作的先后順序,也就是說有可能JVM會為新的Singleton實例分配空間,然后直接賦值給instance成員,然后再去初始化這個Singleton實例。
1
2
3
4
5
6
7
8
9
10
|
public static Singleton getInstance() { if (instance == null ) { synchronized (instance) { if (instance == null ) { instance = new Singleton(); } } } return instance; } |
第四個示例
此代碼初看已經沒有問題,如果在構造方法中出現異常,那么實例將得不到創建
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Singleton { /* 私有構造方法,防止被實例化 */ private Singleton() { } /* 此處使用一個內部類來維護單例 */ private static class SingletonFactory { private static Singleton instance = new Singleton(); } /* 獲取實例 */ public static Singleton getInstance() { return SingletonFactory.instance; } } |
第五個示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private static Singleton instance = null ; private Singleton(){ } public static Singleton getInstance(){ if (instance == null ){ sync(); } return instance; } private static synchronized void sync(){ if (instance == null ){ instance = new Singleton(); System.out.println( "success" ); } } |
到此這篇關于Java 實例解析單例模式的文章就介紹到這了,更多相關Java 單例模式內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/News53231323/article/details/121034929