(1)餓漢式(線程安全)
該方式沒有線程安全問題,當類被卸載時,靜態變量被摧毀,並釋放所佔有的內存,因此在某些特定條件下會耗費內存。
package cn.edu.bjfu.main;
public class MainTest {
public static void main(String[] args) {
Teacher t1 = Teacher.getInstance();
Teacher t2 = Teacher.getInstance();
System.out.println(t1==t2);
}
}
class Teacher {
//本類創建一個對象
private static Teacher t = new Teacher();
//不讓別人創建對象
private Teacher() {}
//使外界可以通過類名. 來調用
public static Teacher getInstance( ) {
return t;
}
}
(2)懶漢式(線程不安全的)
package cn.edu.bjfu.main;
public class MainTest {
public static void main(String[] args) {
Teacher t1 = Teacher.getInstance();
Teacher t2 = Teacher.getInstance();
System.out.println(t1==t2);
}
}
class Teacher {
//本類創建一個對象
private static Teacher t = null;
//不讓別人創建對象
private Teacher() {}
//使外界可以通過類名. 來調用
public static Teacher getInstance() {
if(t == null) {
t = new Teacher();
}
return t;
}
}
因此在某些特定條件下會節約了內存。在多線程環境中,這種實現方法是完全錯誤的,根本不能保證單例的狀態。
(3)懶漢式(優化爲線程安全)
package cn.edu.bjfu.main;
public class MainTest {
public static void main(String[] args) {
Teacher t1 = Teacher.getInstance();
Teacher t2 = Teacher.getInstance();
System.out.println(t1==t2);
}
}
class Teacher {
//本類創建一個對象
private static Teacher t = null;
//不讓別人創建對象
private Teacher() {}
//使外界可以通過類名. 來調用
public static synchronized Teacher getInstance() {
if(t == null) {
t = new Teacher();
}
return t;
}
}
在多線程情形下,synchronized方法通常效率低。
(4)DCL雙檢鎖機制改進優化懶漢式
package cn.edu.bjfu.main;
public class MainTest {
public static void main(String[] args) {
Teacher t1 = Teacher.getInstance();
Teacher t2 = Teacher.getInstance();
System.out.println(t1==t2);
}
}
class Teacher {
//本類創建一個對象
private static Teacher t = null;
//不讓別人創建對象
private Teacher() {}
//使外界可以通過類名. 來調用
public static Teacher getInstance() {
if(t == null) {
synchronized (Teacher.class) {
//某個線程取到了類的鎖,實例化對象前第二次檢查t是否已經被實例化出來,如果沒有,new一個。
if(t == null) {
t = new Teacher();
}
}
}
return t;
}
}