一、什麼是單例設計模式
單例設計模式用來保證一個類在內存中只存在一個對象
二、單例模式構造要點
1、爲了避免其他程序過多的創建該類的對象,先禁止其他程序創建該類對象———–>將構造方法私有化。
2、爲了讓其他程序能夠訪問該類對象,必須在本類中創建該類對象。———>在類中創建一個本類對象。
3、爲了方便其他程序對本類的訪問,對外提供一種訪問對象的方式——–>提供一個方法返回該類對象。
構造單例(餓漢式):
public class SingleTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
System.out.println(s1==s2);
}
}
class Single{
private Single() {
}
private final static Single s = new Single();
//外部不能new新對象,所以只能提供靜態的方法獲得本類對象
public static Single getInstance(){
return s;
}
}
輸出結果
true
類Single確實在內存中只有一份。s1和s2指向同一塊內存。
構造單例(懶漢式)
public class SingleTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
System.out.println(s1==s2);
}
}
class Single{
private Single() {
}
private static Single s = null;
public static Single getInstance(){
if(s==null){
s = new Single();
}
return s;
}
}
懶漢式使用了java中的延遲加載技術,即需要用到對象的時候才創建對象。
餓漢式和懶漢式的區別:餓漢式,Single類進內存,已經創建好對象;懶漢式Single類進內存,對象還沒有創建,調用getInstance後,創建對象。
在多線程中,懶漢式會帶來線程的不安全性。
三、
單例的內存結構
由於在懶漢情況下出現多次判斷,那麼在多線程情況下,會出現單利失效的問題;如果直接在getInstance()方法前面加上synchronized 則執行效率會比較低,每創建一次,都得判斷是否lock住。可以加上雙重判斷,來減少鎖的判斷次數。同步鎖是該類所屬的字節碼文件對象。看下面代碼的妙處;
class Single {
private Single() {
}
private static Single s = null;
public static Single getInstance() {
if (s == null) {
//A進程執行到此處阻塞等待
synchronized (Single.class) {
if (s == null) {
s = new Single();
}
}
}
return s;
}
}