设计模式之模式一单例模式

单例模式分为饿汉跟懒汉两种模式
1)饿汉模式
1. 构造器私有化,防止外部new对象
2. 类的内部创建对象
3. 向外暴露一个静态公共方法获取实例


**饿汉模式1(静态常量)代码如下**
优点:代码简单,类装载的时候完成单例对象的创建。不存在线程同步安全问题
缺点:在类装载的时候完成实例化,没有达到懒加载的效果,创建的对象如果自始至终没有使用,会造成内存的浪费
package com.hy.singlePattern;
/**
* @author hanyong
* @date 2020/5/12 23:07
*/
public class SingleE1 {

private SingleE1(){ }

private final static SingleE1 instance=new SingleE1();

public static SingleE1 getInstance(){
return instance;
}
}
**饿汉模式2(静态代码块)代码如下**
本质同上面一样,都是装载类的时候创建实例,优缺点也是一样
package com.hy.singlePattern;

/**
* @author hanyong
* @date 2020/5/12 23:24
*/
public class SingleE2 {

private final static SingleE2 instance;
private SingleE2(){}
static {
instance=new SingleE2();
}
public static SingleE2 getInstance(){
return instance;
}
}

2)懒汉模式
**懒汉模式1,线程不安全 代码如下**
优缺点:起到懒加载效果,及就是调用才创建,但是只能满足单线程使用,多线程场景会有问题
当有一个线程if(null==instance)满足这个条件走到if里面但是还没有创建对象,另一个线程也判断满足条件走进创建的代码。则会产生多个实例。(不推荐使用)
package com.hy.singlePattern;

/**
* @author hanyong
* @date 2020/5/12 23:32
*/
public class SingleL1 {
private SingleL1(){};
private static SingleL1 instance;
public static SingleL1 getInstance(){
if(null==instance){
instance=new SingleL1();
}
return instance;
}
}

**懒汉模式2 synchronized方法枷锁保证线程安全 代码如下**
优缺点:解决线程安全,效率太低,每个线程想要获得类的实例时执行 getInstance方法都会进行同步。(不推荐使用)
package com.hy.singlePattern;

/**
* @author hanyong
* @date 2020/5/12 23:43
*/
public class SingleL2 {
private SingleL2(){};
private static SingleL2 instance;
public static synchronized SingleL2 getInstance(){
if(instance==null){
instance=new SingleL2();
}
return instance;
}
}

**懒汉模式3 synchronized代码块保证线程安全 代码如下**
缺点:对上面的改进,想着同步产生实例化,但是线程不安全,当有一个判断if(instance==null)满足后还未来的季执行,下一个线程也进行了判断满足条件。则会创建多个实例。**所有这种方式是错误的。不能使用**
package com.hy.singlePattern;
/**
* @author hanyong
* @date 2020/5/12 23:52
*/
public class SingleL3 {
private SingleL3(){};
private static SingleL3 instance;
public static SingleL3 getInstance(){
if(instance==null){
synchronized (SingleL3.class){
instance=new SingleL3();
}
}
return instance;
}
}

**懒汉模式4 双重检查保障线程安全 代码如下**
优缺点:双重检查,进行两次判断,保证线程安全;实例化代码只执行一次。当后面进入创建实例方法时判断instance不为null直接return
**代码效率高,线程安全。推荐使用**
package com.hy.singlePattern;
/**
* @author hanyong
* @date 2020/5/13 0:01
*/
public class SingleL4 {
private SingleL4(){};
private volatile static SingleL4 instance;
public static SingleL4 getInstance(){
if(instance==null){
synchronized (SingleL4.class){
if(instance==null){
instance=new SingleL4();
}
}
}
return instance;
}
}

**懒汉模式5 静态内部类应用实例 代码如下**
优缺点:采用类装载的机制来保证初始化实例时只有一个线程;静态内部类方式在SingleL5 类装载时并不会立即实例化,而是在被需要的时候才会进行实例化,也就时调用getInstance的时候才会装载SingleL5Instance类,再进行实例化SingleL5 。这样实现了懒加载; 类的静态属性只会在第一次加载的时候初始化,所以jvm确保了线程安全。**线程安全,效率高推荐使用**
package com.hy.singlePattern;
/**
* @author hanyong
* @date 2020/5/13 0:07
*/
public class SingleL5 {
private SingleL5(){}
private static class SingleL5Instance{
private final static SingleL5 INSTANCE=new SingleL5();
}
public static SingleL5 getInstance(){
return SingleL5Instance.INSTANCE;
}
}

**懒汉模式6 枚举方式实现 代码如下**
优缺点:避免多线程问题,还能防止反序列化重新创建新的对象。**推荐使用**
package com.hy.singlePattern;

/**
* @author hanyong
* @date 2020/5/13 0:22
*/
public class SingleL6Test {

public static void main(String[] args) {
SingleL6 in1=SingleL6.INSTANCE;
SingleL6 in2=SingleL6.INSTANCE;
System.out.println(in1==in2);
in1.test();
}
}
enum SingleL6{
INSTANCE;
public void test(){
System.out.println("whh");
}
}

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}
posted @ 2020-09-11 00:51  yongzhewuwei  阅读(136)  评论(0编辑  收藏  举报