揭秘设计模式之单例模式
Posted 醉酒的小男人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了揭秘设计模式之单例模式相关的知识,希望对你有一定的参考价值。
什么是单例模式
单例模式是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。属于创建型模式。单例就是一个类只能有一个对象,单例模式在生活里也比较普遍,比如:像打印机、处理器(单核)、皇帝、太子、月亮、太阳等等,它们都是稀有资源,只能有一个实例对象。
代码案例
饿汉式
package singleton;
public class HungrySingleton {
//先静态、后动态
//先属性、后方法
//先上后下
private static final HungrySingleton INSTANCE = new HungrySingleton();
//构造方法私有化
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return INSTANCE;
}
}
懒汉式
package singleton;
public class LazySimpleSingleton {
private LazySimpleSingleton(){}
private static LazySimpleSingleton lazySimpleSingleton;
public synchronized static LazySimpleSingleton getInstance(){
if(lazySimpleSingleton == null){
lazySimpleSingleton = new LazySimpleSingleton();
}
return lazySimpleSingleton;
}
}
双重检查锁
package singleton;
/**
* 双重检查锁
*/
public class LazyDoubleCheckSingleton {
private LazyDoubleCheckSingleton(){}
//volatile禁止指令重排序通过内存屏障
private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton;
public static LazyDoubleCheckSingleton getInstance(){
if(lazyDoubleCheckSingleton == null){
synchronized (LazyDoubleCheckSingleton.class){
if(lazyDoubleCheckSingleton == null){
lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
//1.分配内存给这个对象
//2.初始化对象
//3.设置lazy指向刚分配的内存地址
}
}
}
return lazyDoubleCheckSingleton;
}
}
静态内部类
package singleton;
public class LazyInnerClassSingleton {
private LazyInnerClassSingleton(){}
public static final LazyInnerClassSingleton getInstance(){
if(LazyHolder.LAZY != null){
throw new RuntimeException("不许去创建多个实例");
}
return LazyHolder.LAZY;
}
//默认不加载
private static class LazyHolder{
private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
}
}
枚举式
package singleton;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 枚举式单例
*/
public enum EnumSingleton {
INSTANCE;
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static EnumSingleton getInstance(){
return INSTANCE;
}
public static void main(String[] args) {
try {
EnumSingleton instance1 = null;
EnumSingleton instance2 = EnumSingleton.getInstance();
instance2.setData(new Object());
FileOutputStream fos = new FileOutputStream("EnumSingleton.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(instance2);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("EnumSingleton.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
instance1 = (EnumSingleton)ois.readObject();
ois.close();
System.out.println(instance1.getData());
System.out.println(instance2.getData());
System.out.println(instance1.getData()==instance2.getData());
}catch (Exception e){
e.printStackTrace();
}
}
}
容器式
package singleton;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 类似于spring中的容器也是使用的Map
*/
public class ContainerSingleton {
private ContainerSingleton(){}
private static Map<String,Object> ioc = new ConcurrentHashMap<>();
public static Object getBean(String className){
synchronized (ioc){
if(!ioc.containsKey(className)){
Object obj = null;
try {
obj = Class.forName(className).newInstance();
ioc.put(className,obj);
}catch (Exception e){
e.printStackTrace();
}
return obj;
}else{
return ioc.get(className);
}
}
}
}
序列化
package singleton;
import java.io.*;
/**
* 反序列化导致破坏单例模式
*/
public class SeriableSingleton implements Serializable {
private SeriableSingleton(){}
public static final SeriableSingleton INSTANCE = new SeriableSingleton();
/**
* 当JVM从内存中反序列化地"组装"一个新对象时,就会自动调用这个
* readResolve方法来返回我们指定好的对象了,单例规则也就得到了保证.
* @return
*/
public static SeriableSingleton getInstance(){
return INSTANCE;
}
private Object readResolve(){
return INSTANCE;
}
/**
* 1.序列化就是把内存中的状态通过转换成字节码的形式,
* 从而转换成一个I/O流,写入其它地方比如磁盘、网络等,内存中的状态会永久保存下来。
* 2.反序列化就是将已经持久化的字节码内容转换成I/O流,通过I/O流的读取,
* 把读取的内容转换成java对象,在转换过程中会重新创建对象new.
* @param args
*/
public static void main(String[] args) {
SeriableSingleton s1 = null;
SeriableSingleton s2 =SeriableSingleton.getInstance();
FileOutputStream fos = null;
try {
fos = new FileOutputStream("SeriableSingleton.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s2);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("SeriableSingleton.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
s1 = (SeriableSingleton)ois.readObject();
ois.close();
System.out.println(s1);
System.out.println(s2);
System.out.println(s1==s2);
}catch (Exception e){
e.printStackTrace();
}
}
}
本地线程
package singleton;
public class ThreadLocalSingleton {
private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance = new ThreadLocal<ThreadLocalSingleton>(){
@Override
protected ThreadLocalSingleton initialValue() {
return super.initialValue();
}
};
private ThreadLocalSingleton(){}
public static ThreadLocalSingleton getInstance(){
return threadLocalInstance.get();
}
public static void main(String[] args) {
System.out.println(ThreadLocalSingleton.getInstance());
System.out.println(ThreadLocalSingleton.getInstance());
System.out.println(ThreadLocalSingleton.getInstance());
System.out.println(ThreadLocalSingleton.getInstance());
System.out.println(ThreadLocalSingleton.getInstance());
}
}
以上是关于揭秘设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章