单例模式
Posted lusaisai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式相关的知识,希望对你有一定的参考价值。
问题的由来:
为什么?
多个线程操作不同实例对象。多个线程要操作同一对象,要保证对象的唯一性
解决的问题:
实例化过程中只实例化一次
解决的思路
有一个实例化的过程(只有一次),产生实例化对象 new
提供返回实例对象的方法 getInstace()
单例模式的分类
饿汉式
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了
/**
* *是否 Lazy 初始化:否
* *是否多线程安全:是
* *实现难度:易
* *描述:这种方式比较常用,但容易产生垃圾对象。
* *优点:没有加锁,执行效率会提高。
* *缺点:类加载时就初始化,浪费内存。
* *它基于 classloder 机制避免了多线程的同步问题,
* * 不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,
* * 在单例模式中大多数都是调用 getInstance 方法,
* * 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,
* * 这时候初始化 instance 显然没有达到 lazy loading 的效果。
*
*/
public class HungerySingleton {
//加载的时候就产生的实例对象,ClassLoader
private byte[] data=new byte[1024];
private static HungerySingleton instance=new HungerySingleton();
private HungerySingleton(){
}
//返回实例对象
public static HungerySingleton getInstance(){
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
System.out.println(HungerySingleton.getInstance());
}).start();
}
}
}
懒汉式
/**
* *是否 Lazy 初始化:是
* *是否多线程安全:否
* *实现难度:易
* *描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
* *这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
*/
public class HungerySingleton {
//加载的时候就产生的实例对象,ClassLoader
private byte[] data=new byte[1024];
private static HungerySingleton instance=new HungerySingleton();
private HungerySingleton(){
}
//返回实例对象
public static HungerySingleton getInstance(){
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
System.out.println(HungerySingleton.getInstance());
}).start();
}
}
}
线程不安全:不能保证实例对象的唯一性
懒加载+性能好
懒汉式+同步方法
线程安全
懒加载
性能:synchronized 退化到了串行执行
public class HoonSynSingleton { private static HoonSynSingleton instance=null; private HoonSynSingleton(){ } public synchronized static HoonSynSingleton getInstance(){ if(null==instance) instance=new HoonSynSingleton(); return instance; } public static void main(String[] args) { for (int i = 0; i < 20; i++) { new Thread(()->{ System.out.println(HoonSynSingleton.getInstance()); }).start(); } } }
public class HoonSynSingletonDemo { private static HoonSynSingletonDemo instance=null; private HoonSynSingletonDemo(){ } public static HoonSynSingletonDemo getInstance(){ if(null==instance) synchronized (HoonSynSingletonDemo.class){ instance=new HoonSynSingletonDemo(); } return instance; } public static void main(String[] args) { for (int i = 0; i < 20; i++) { new Thread(()->{ System.out.println(HoonSynSingletonDemo.getInstance()); }).start(); } } }
DCL :Double-Check-Locking
public class DCL { Connection conn; Socket socket; private volatile static DCL instance=null; private DCL(){ } public static DCL getInstance(){ if(null==instance) synchronized (DCL.class){ if(null==instance) if(null==instance) instance=new DCL(); } return instance; } public static void main(String[] args) { for (int i = 0; i < 20; i++) { new Thread(()->{ System.out.println(DCL.getInstance()); }).start(); } } }
性能比较好
懒加载
线程的安全性
问题:因为指令重排一起空指针异常
Holder
声明类的时候,成员变量中不声明实例变量,而放到内部静态类中,
public class HolderDemo { private HolderDemo(){ } private static class Holder{ private static HolderDemo instance=new HolderDemo(); } //懒加载 //synchronized //<init> public static HolderDemo getInstance(){ return Holder.instance; } //广泛的一种单例模式 }
public class HoonSingleton { private static HoonSingleton instance=null; private HoonSingleton(){ } public static HoonSingleton getInstance(){ if(null==instance) instance=new HoonSingleton(); return instance; } public static void main(String[] args) { for (int i = 0; i < 20; i++) { new Thread(()->{ System.out.println(HoonSingleton.getInstance()); }).start(); } } }
枚举
public enum EnumSingleton { INSTANCE; public static EnumSingleton getInstance(){ return INSTANCE; } }
public enum EnumDemo { //常量,在加载的时候实例化一次,方法区 A,B,C,D; int i=10; int j=20; public static void m1(){ System.out.println("method"); } public static void main(String[] args) { A.m1(); B.m1(); C.m1(); D.m1(); System.out.println(A.getClass().getName()); System.out.println(B.getClass().getName()); System.out.println(C.getClass().getName()); System.out.println(D.getClass().getName()); } }
public class EnumSingletonDemo { private EnumSingletonDemo(){ } //延迟加载 private enum EnumHolder{ INSTANCE; private EnumSingletonDemo instance=null; EnumHolder(){ instance=new EnumSingletonDemo(); } private EnumSingletonDemo getInstance(){ return instance; } }//懒加载 public static EnumSingletonDemo getInstance(){ return EnumHolder.INSTANCE.instance; } }
以上是关于单例模式的主要内容,如果未能解决你的问题,请参考以下文章