七种单例设计模式
饿汉式懒汉式懒汉式 + 同步方法Double-CheckVolatile +Double-CheckHolder 方式枚举方式
饿汉式
package day0518
;
public final class Singleton {
private byte [] data
= new byte[1024] ;
private static Singleton instance
= new Singleton();
private Singleton() {
}
public static Singleton
getInstance(){
return instance
;
}
}
饿汉式的关键在于instance 作为类变量并且直接得到了初始化,如果住的的使用了Singleton类难么instance实例将直接完成创建,包括其中的实例变量都会得到初始化,1k的空间的data会被同时创建。
懒汉式
package day0518
;
public final class Singleton {
private byte[] data
= new byte[1024];
private static Singleton instance
= null
;
private Singleton() {
}
public static Singleton
getInstance() {
if (null
== instance
) {
instance
= new Singleton();
}
return instance
;
}
}
所谓懒汉式就是在使用实例的时候再去创建(用时创建)。但是多线程的情况下是懒汉式是线程不安全的。懒汉式可以保证实例的懒加载,但是无法保证实例的唯一。
懒汉式 + 同步方法
package day0518
;
public final class Singleton {
private byte[] data
= new byte[1024];
private static Singleton instance
= null
;
private Singleton() {
}
public static synchronized Singleton
getInstance() {
if (null
== instance
) {
instance
= new Singleton();
}
return instance
;
}
}
采用懒汉式+数据同步的方式既满足了懒加载又能百分百的保证instance 实例的唯一性,但是synchronized 关键字天生的排他性导致getInstance 方法只能在同一时刻被一个线程访问,性能低下。
Double-Check
package day0518
;
import java
.net
.Socket
;
import java
.sql
.Connection
;
public final class Singleton {
private byte[] data
= new byte[1024];
private static Singleton instance
= null
;
Connection conn
;
Socket socket
;
private Singleton() {
}
public static synchronized Singleton
getInstance() {
if (null
== instance
) {
synchronized (Singleton
.class) {
if (null
== instance
) {
instance
= new Singleton();
}
}
}
return instance
;
}
}
很聪明的一个方式通过两次校验,第一次判断当instance 为null的时候进入同步代码块,避免每次都需要进入同步代码快;第二次校验instance 为空则为其创建实例。但是这种方式在多线程的情况下有可能会造成空指针异常。有可能在成员变量实例化conn 、socket的发生在instance实例化之后。
Volatile +Double-Check
只需要在Double-Check 的模式代码上加个volatile。
package day0518
;
import java
.net
.Socket
;
import java
.sql
.Connection
;
public final class Singleton {
private byte[] data
= new byte[1024];
private static volatile Singleton instance
= null
;
Connection conn
;
Socket socket
;
private Singleton() {
}
public static synchronized Singleton
getInstance() {
if (null
== instance
) {
synchronized (Singleton
.class) {
if (null
== instance
) {
instance
= new Singleton();
}
}
}
return instance
;
}
}
Holder 方式
package day0518
;
import java
.net
.Socket
;
import java
.sql
.Connection
;
public final class Singleton {
private byte[] data
= new byte[1024];
private Singleton() {
}
private static class Holder {
private static Singleton instance
= new Singleton();
}
public static synchronized Singleton
getInstance() {
return Holder
.instance
;
}
}
Holder方式完全是借助了类的加载的特点。 在Singleton 类中并没有instance 的静态成员,而是将其放到了静态内部类Holder中,因此在Singleton 类的初始化过程中比不过不不会创建Singleton 的实例,Holder 类中定义了Singleton 的静态变量,并且直接进行了实例化,当Holder 被主动使用的时候则会创建Singleton 的实例,Singleton 实例的创建过程在java程序编译时期收集到()方法中,该方法又是同步方法,可以保证内存的可见性、jvm指令的顺序性和原子性。Holder方式的单例是最好的设计之一,也是目前使用比较广的设计。
枚举方式