一、恶汉模式 (线程安全)
instance作为类变量,并且直接得到初始化
public class Singleton01{
//创建静态变量并进行初始化,并且jvm加载时就会进行实例,保证该实例只有一个
//但是对于多线程而言,这样的效率并不高,造成资源的浪费
private static final Singleton01 instance = new Singleton01();
private Singleton01(){}//将构造函数访问权限修改成private,即外部无法通过new进行实例化调用
public static Singleton01 getInstance(){
return instance;
}
二、懒汉式(非线程安全)
在使用类实例的时候再去创建
//解决了饿汉式的资源浪费的缺点,但是只能在单线程下进行,如果多线程下会不安全,容易被实例化多次
public class Singleton02{
//创建静态变量,但不初始化,等待使用时进行初始化
private static Singleton02 instance=null;
private Singleton02(){}
public static Singleton02 getInstance(){
if(instance==null){
instance=new Singleton02();
}
return instance;
}
}
三、懒汉式+同步方法//该线程安全版本,是在初始化方法上加上同步机制synchronized,是的线程安全,但是这种全局同步,会
使得在多线程并发情况下,执行效率不高,故而不推荐
public class Singleton03 {
private static Singleton03 instance=null;
private Singleton03(){}
// 加入 synchronized
private synchronized Singleton03 getInstance(){
if(instance==null){
instance=new Singleton03();
}
return instance;
}
}
扫描二维码关注公众号,回复:
4931871 查看本文章
四、Double-Check(容易引起空指针异常,线程安全)
会引起类成员变量的实例化conn和socket放生在instance实例化之后。由于JVM运行时指令重排导致。
//该线程安全版本,是在线程不安全版本上,使用静态块初始化instance实例,通过静态变量jvm初始化规则
静态变量/静态块-非静态变量/构造块-构造函数
package com.zl.step14;
import java.net.Socket;
import java.sql.Connection;
public class Singleton04 {
private static Singleton04 instance=null;
Connection conn ;
Socket socket ;
private Singleton04(){
this.conn = null ; // 初始化conn
this.socket = null ; // 初始化socket
}
// 加入 synchronized
private static Singleton04 getInstance(){
if(instance==null){
synchronized (Singleton04.class) {
if(instance==null){
instance=new Singleton04();
}
}
}
return instance;
}
}
五、 Volatile+Double-Cheack
Double-Cheack会引起类成员变量的实例化conn和socket放生在instance实例化之后。由于JVM运行时指令重排导致。
volatile关键字可以防止这种重排序的发生。
修改代码:
private volatile static Singleton05 instance=null;
package com.zl.step14;
import java.net.Socket;
import java.sql.Connection;
public class Singleton05 {
private volatile static Singleton05 instance=null;
Connection conn ;
Socket socket ;
private Singleton05(){
this.conn = null ; // 初始化conn
this.socket = null ; // 初始化socket
}
// 加入 synchronized
private static Singleton05 getInstance(){
if(instance==null){
synchronized (Singleton05.class) {
if(instance==null){
instance=new Singleton05();
}
}
}
return instance;
}
}
六、Holder方式
/**
* 在Singleton类中并没有instance的静态成员,
* 而是将其放到了静态内部类Holder之中
* 因为在Singleton创建的时候,并不会创建Singleton的实例
* Holder类中定义了Singleton的惊天变量,并且直接进行实例化
* 当Holder被主动引用的时候就会创建Singleton的实例
* Singleton实例的创建过程在Java程序编译时期手机至<clint>()方法中
* 该方法又是同步方法,同步方法可以保证内存的可见性、JVM指令的顺序性和原子性
*
*
*/
public class Singleton06 {
private static final class SingletonHolder{
private static final Singleton06 instance=new Singleton06();
}
private Singleton06(){}
public static Singleton06 getInstance(){
return SingletonHolder.instance;
}
}
七、枚举方式
public class Singleton07 {
private Singleton07(){}
private static Singleton07 getInstance(){
return SingletonHolder.INSTANCE.getInstance();
}
public enum SingletonHolder{
INSTANCE;
private Singleton07 instance=null;
SingletonHolder(){
instance=new Singleton07();
}
public Singleton07 getInstance(){
return instance;
}
}
}