前言
一、單例模式的介紹
二、單例模式的 8 種實(shí)現(xiàn)方式(懶漢式要注意線程安全問題)
1、餓漢式(靜態(tài)常量)
代碼示例
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//餓漢式(靜態(tài)變量)
class Singleton {
//1. 構(gòu)造器私有化, 外部能 new
private Singleton() {
}
//2.本類內(nèi)部創(chuàng)建對象實(shí)例
private final static Singleton instance = new Singleton();
//3. 提供一個公有的靜態(tài)方法,返回實(shí)例對象
public static Singleton getInstance() {
return instance;
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
優(yōu)缺點(diǎn):可能會造成內(nèi)存的浪費(fèi),但也只能浪費(fèi)內(nèi)存
2、餓漢式(靜態(tài)代碼塊)
代碼示例
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//餓漢式(靜態(tài)變量)
class Singleton {
//1. 構(gòu)造器私有化, 外部能 new
private Singleton() {
}
//2.本類內(nèi)部創(chuàng)建對象實(shí)例
// private final static Singleton instance = new Singleton();
private static Singleton instance;
static {
//使用靜態(tài)代碼塊,不再使用 final 修飾為常量
instance = new Singleton();
}
//3. 提供一個公有的靜態(tài)方法,返回實(shí)例對象
public static Singleton getInstance() {
return instance;
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
3、懶漢式(線程不安全)不推薦
代碼示例
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//餓漢式(靜態(tài)變量)
class Singleton {
//1. 構(gòu)造器私有化, 外部能 new
private Singleton() {
}
//2.本類內(nèi)部創(chuàng)建對象實(shí)例
private static Singleton instance;
//3. 提供一個公有的靜態(tài)方法,返回實(shí)例對象
public static Singleton getInstance() {
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
缺點(diǎn):多線程不安全
4、懶漢式(線程安全,同步方法)添加 synchronized 關(guān)鍵字
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//餓漢式(靜態(tài)變量)
class Singleton {
//1. 構(gòu)造器私有化, 外部能 new
private Singleton() {
}
//2.本類內(nèi)部創(chuàng)建對象實(shí)例
private static Singleton instance;
//3. 提供一個公有的靜態(tài)方法,返回實(shí)例對象
/** 添加 synchronized 關(guān)鍵字保證線程安全 */
public static synchronized Singleton getInstance() {
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
缺點(diǎn)效率太低
5、懶漢式(同步代碼塊)不能使用,解決不了線程安全問題
6、懶漢式(雙重檢查加 volatile關(guān)鍵字)推薦使用
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//餓漢式(靜態(tài)變量)
class Singleton {
//1. 構(gòu)造器私有化, 外部能 new
private Singleton() {
}
//2.本類內(nèi)部創(chuàng)建對象實(shí)例,添加 volatile 保證有序性和可見性
private static volatile Singleton instance;
//3. 提供一個公有的靜態(tài)方法,返回實(shí)例對象
/** 雙重檢查加 volatile 關(guān)鍵字 */
public static Singleton getInstance() {
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
7、靜態(tài)內(nèi)部類
在類加載時,靜態(tài)內(nèi)部類沒有調(diào)用是不會進(jìn)行類加載的,當(dāng)被調(diào)用時才會被加載,而且只加載一次,加載時線程安全
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//餓漢式(靜態(tài)變量)
class Singleton {
//1. 構(gòu)造器私有化, 外部能 new
private Singleton() {
}
//提供一個靜態(tài)內(nèi)部類,根據(jù)JVM底層機(jī)制保證線程安全
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//3. 提供一個公有的靜態(tài)方法,返回實(shí)例對象
public static Singleton getInstance() {
Singleton instance = SingletonInstance.INSTANCE;
return instance;
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
優(yōu)缺點(diǎn)
8、使用枚舉實(shí)現(xiàn)單例懶加載
package tanchishell.SJMS;
public class SingletonTest01 {
public static void main(String[] args) {
//測試
Singleton instance = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
instance.method();
}
}
enum Singleton{
INSTANCE;
public void method(){
System.out.println("hello,world");
}
}
輸出
true
instance.hashCode=460141958
instance2.hashCode=460141958
hello,world
三、JDKの RunTime 類使用的是單例模式
文章來源:http://www.zghlxwxcb.cn/news/detail-420094.html
四、單例模式注意事項(xiàng)和細(xì)節(jié)說明
文章來源地址http://www.zghlxwxcb.cn/news/detail-420094.html
到了這里,關(guān)于第四章 單例模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!