单例模式分成两种,懒汉模式,饿汉模式
饿汉模式比较简单,虽然初始化时会消耗性能,但是没有线程安全问题。
/**
* 饿汉-单例模式
*
* @author 柚柚
*
*/
public class SingletonHungryMan {
// 构造方法私有化
private SingletonHungryMan() {}
// 饿汉式创建单例对象
private static SingletonHungryMan singleton = new SingletonHungryMan();
public static SingletonHungryMan getInstance() {
return singleton;
}
}
懒汉模式,按需加载,需要注意线程安全问题。
/**
* 懒汉-单例模式
* @author 柚柚
* 特点:第一次调用才初始化,避免内存浪费。
*
*/
public class SingletonLazyMan {
// 构造方法私有化
private SingletonLazyMan() {}
private static SingletonLazyMan singleton;
/*
* 懒汉式创建单例模式 由于懒汉式是非线程安全, 所以加上线程锁保证线程安全
*/
public static synchronized SingletonLazyMan getInstance() {
if (singleton == null) {
singleton = new SingletonLazyMan();
}
return singleton;
}
}
/**
* 懒汉-单例模式
* @author 柚柚
* 特点:第一次调用才初始化,避免内存浪费。
*
*/
public class SingletonLazyMan2 {
// 构造方法私有化
private SingletonLazyMan2() {}
//volatile 可见性
private volatile static SingletonLazyMan2 singleton;
//双重检验锁 --锁.class类
public static SingletonLazyMan2 getInstance() {
if (singleton == null) {
synchronized (SingletonLazyMan2.class) {
if (singleton == null) {
singleton = new SingletonLazyMan2();
}
}
}
return singleton;
}
}
破坏单例的几种方式与解决方法
package demo.huang.cn.design;
import java.io.*;
import java.lang.reflect.Constructor;
public class SingletonTset {
public static void main(String[] args) {
//
try {
// checkByFileStream();
checkByConstructor();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 反射
*
* @throws Exception
*/
public static void checkByConstructor() throws Exception {
SingletonHungryMan singleton = SingletonHungryMan.getInstance();
Class<SingletonHungryMan> singletonClass = SingletonHungryMan.class;
Constructor<SingletonHungryMan> constructor = singletonClass.getDeclaredConstructor();
constructor.setAccessible(true);
SingletonHungryMan singleton1 = constructor.newInstance();
System.out.println(singleton);
System.out.println(singleton1);
}
/**
* 序列化 反序列获取对象
*
* @throws IOException
* @throws ClassNotFoundException
* @throws InterruptedException
*/
public static void checkByFileStream() throws IOException, ClassNotFoundException, InterruptedException {
SingletonHungryMan e = SingletonHungryMan.getInstance();
System.out.println("单例对象:" + e);
FileOutputStream fileOut = null;
ObjectOutputStream out = null;
FileInputStream fileIn = null;
ObjectInputStream in = null;
SingletonHungryMan e2 = null;
try {
// 序列化一个对象 存入D:\\employee.txt
fileOut = new FileOutputStream("D:\\employee.txt");
out = new ObjectOutputStream(fileOut);
out.writeObject(e);
Thread.sleep(100);
// 创建反序列化流
fileIn = new FileInputStream("D:\\employee.txt");
in = new ObjectInputStream(fileIn);
e = (SingletonHungryMan) in.readObject();
fileIn = new FileInputStream("D:\\employee.txt");
in = new ObjectInputStream(fileIn);
e2 = (SingletonHungryMan) in.readObject();
} finally {
// 释放资源
out.close();
fileOut.close();
in.close();
fileIn.close();
}
System.out.println("序列化对象:" + e);
System.out.println("序列化对象:" + e2);
// 可以看出三个对象都不是同一个对象
// 单例对象:demo.huang.cn.design.SingletonHungryMan@15db9742
// 序列化对象:demo.huang.cn.design.SingletonHungryMan@723279cf
// 序列化对象:demo.huang.cn.design.SingletonHungryMan@10f87f48
}
}
…
如果还有其它技术可以破坏单例…
给我留个言,谢谢。