目录
- /**
- * 饿汉式:静态变量创建类的对象
- */
- public class Singleton {
- //私有构造方法
- private Singleton() {}
-
- //在成员位置创建该类的对象
- private static Singleton instance = new Singleton();
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- return instance;
- }
- }
-
-
- public class Client {
- public static void main(String[] args) {
- Singleton instance1 = Singleton.getInstance();
- Singleton instance2 = Singleton.getInstance();
- System.out.println(instance1 == instance2);//true
- }
- }
- /**
- * 饿汉式:在静态代码块中创建该类对象
- */
- public class Singleton {
-
- //私有构造方法
- private Singleton() {}
-
- //在成员位置创建该类的对象
- private static Singleton instance;
-
- static {
- instance = new Singleton();
- }
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- return instance;
- }
- }
-
-
- public class Client {
- public static void main(String[] args) {
- Singleton instance1 = Singleton.getInstance();
- Singleton instance2 = Singleton.getInstance();
- System.out.println(instance1 == instance2);//true
- }
- }
- /**
- * 懒汉式:线程不安全
- */
- public class Singleton {
- //私有构造方法
- private Singleton() {
- System.out.println(Thread.currentThread().getName() + "OK");
- }
-
- //在成员位置创建该类的对象
- private static Singleton instance;
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
-
- if (instance == null) {
- instance = new Singleton();
- }
- return instance;
- }
- }
- /**
- * 懒汉式:线程安全!!!
- */
- public class Singleton {
- //私有构造方法
- private Singleton() {
- System.out.println(Thread.currentThread().getName()+"OK");
- }
-
- //在成员位置创建该类的对象
- private static Singleton instance;
-
- //对外提供静态方法获取该对象
- public static synchronized Singleton getInstance() {
-
- if(instance == null) {
- instance = new Singleton();
- }
- return instance;
- }
- }
- /**
- * 双重检查方式
- * 对于getInstance()方法来说,绝大部分的操作都是读操作,读操作是线程安全的,
- * 所以我们没必让每个线程必须持有锁才能调用该方法,我们需要调整加锁的时机。
- *
- * 在多线程的情况下,可能会出现空指针问题,出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作。
- * 需要使用volatile关键字,volatile关键字可以保证可见性和有序性。
- */
- public class Singleton {
-
- //私有构造方法
- private Singleton() {
- System.out.println(Thread.currentThread().getName()+"OK");
- }
-
- private static volatile Singleton instance;//volatile关键字可以保证可见性和有序性。
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- //第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实例
- if(instance == null) {
- synchronized (Singleton.class) {
- //抢到锁之后再次判断是否为null
- if(instance == null) {
- instance = new Singleton();
- /**
- * 1.分配内存空间
- * 2.执行构造方法,初始化对象
- * 3.把这个对象指向这个空间
- *
- * A线程:由于指令重排,执行顺序为132
- * B线程:发现空间已经占用了,直接返回,但此时LazyMan还没有完成构造,出现空指针
- */
- }
- }
- }
- return instance;
- }
- }
- /**
- * 静态内部类方式
- *
- * 第一次加载Singleton类时不会去初始化INSTANCE,
- * 只有第一次调用getInstance,虚拟机加载SingletonHolder并初始化INSTANCE,
- * 这样不仅能确保线程安全,也能保证Singleton类的唯一性。
- *
- * 静态内部类单例模式是一种优秀的单例模式,是开源项目中比较常用的一种单例模式。
- * 在没有加任何锁的情况下,保证了多线程下的安全,并且没有任何性能影响和空间的浪费。
- */
- public class Singleton {
-
- //私有构造方法
- private Singleton() {
- System.out.println(Thread.currentThread().getName() + "OK");
- }
-
- //静态内部类
- private static class SingletonHolder {
- private static final Singleton INSTANCE = new Singleton();
- }
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- return SingletonHolder.INSTANCE;
- }
- }
- public class Client {
- public static void main(String[] args) {
- for (int i = 0; i < 10; i++) {
- new Thread(()->{
- Singleton.getInstance();
- }).start();
- }
- }
- }
- /**
- * 枚举方式
- */
- public enum Singleton {
- INSTANCE;
-
- public static Singleton getInstance() {
- return INSTANCE;
- }
- }
-
-
- public class Client {
- public static void main(String[] args) {
- Singleton instance1 = Singleton.INSTANCE;
- Singleton instance2 = Singleton.INSTANCE;
- System.out.println(instance1==instance2);//true
- }
- }
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * 尝试反射破坏
- */
- public class Test {
- public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- Constructor
declaredConstructor = Singleton.class.getDeclaredConstructor(null); - declaredConstructor.setAccessible(true);
- Singleton instance = declaredConstructor.newInstance();
- System.out.println(instance);//NoSuchMethodException,没有空参构造方法
- }
- }


- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * 尝试反射破坏
- */
- public class Test2 {
- public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- Singleton instance1 = Singleton.getInstance();
- Constructor
declaredConstructor = Singleton.class.getDeclaredConstructor(String.class, int.class); - declaredConstructor.setAccessible(true);
- Singleton instance2 = declaredConstructor.newInstance();
- System.out.println(instance1);
- System.out.println(instance2);//IllegalArgumentException: Cannot reflectively create enum objects
- }
- }
- import java.io.Serializable;
-
- /**
- * 静态内部类方式
- */
- public class Singleton implements Serializable{
-
- //私有构造方法
- private Singleton() {
- }
-
- //静态内部类
- private static class SingletonHolder {
- private static final Singleton INSTANCE = new Singleton();
- }
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- return SingletonHolder.INSTANCE;
- }
- }
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
-
- /**
- * 序列化反序列化破坏单例模式
- */
- public class Test {
- public static void main(String[] args) throws Exception {
- //往文件中写对象
- // writeObject2File();
- //从文件中读取对象
- Singleton s1 = readObjectFromFile();
- Singleton s2 = readObjectFromFile();
-
- //判断两个反序列化后的对象是否是同一个对象
- System.out.println(s1 == s2);//false
- }
-
- /**
- * 从文件中读数据
- * @return
- * @throws Exception
- */
- private static Singleton readObjectFromFile() throws Exception {
- //1.创建对象输入流对象
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
- //2.第一个读取Singleton对象
- Singleton instance = (Singleton) ois.readObject();
- //3.释放资源
- ois.close();
- //4.返回结果
- return instance;
- }
-
- /**
- * 向文件中写数据
- * @throws Exception
- */
- public static void writeObject2File() throws Exception {
- //1.获取Singleton类的对象
- Singleton instance = Singleton.getInstance();
- //2.创建对象输出流
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
- //3.将instance对象写出到文件中
- oos.writeObject(instance);
- //4.释放资源
- oos.close();
- }
- }
- import java.io.Serializable;
-
- /**
- * 静态内部类方式
- */
- public class Singleton implements Serializable{
-
- //私有构造方法
- private Singleton() {
- }
-
- //静态内部类
- private static class SingletonHolder {
- private static final Singleton INSTANCE = new Singleton();
- }
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- return SingletonHolder.INSTANCE;
- }
- }
- import java.lang.reflect.Constructor;
-
- /**
- * 反射破坏单例模式
- */
- public class Test {
- public static void main(String[] args) throws Exception {
- //获取Singleton类的字节码对象
- Class c = Singleton.class;
- //获取Singleton类的私有无参构造方法对象
- Constructor constructor = c.getDeclaredConstructor();
- //取消访问检查
- constructor.setAccessible(true);
-
- //创建Singleton类的对象s1
- Singleton s1 = (Singleton) constructor.newInstance();
- //创建Singleton类的对象s2
- Singleton s2 = (Singleton) constructor.newInstance();
-
- //判断通过反射创建的两个Singleton对象是否是同一个对象
- System.out.println(s1 == s2);//false
- }
- }
- import java.io.Serializable;
-
- /**
- * 静态内部类方式:解决序列化反序列化破解单例模式
- */
- public class Singleton implements Serializable{
-
- //私有构造方法
- private Singleton() {
- }
-
- //静态内部类
- private static class SingletonHolder {
- private static final Singleton INSTANCE = new Singleton();
- }
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- /**
- * 下面是为了解决序列化反序列化破解单例模式
- * 当进行反序列化时,会自动调用该方法,将该方法的返回值直接返回
- */
- private Object readResolve() {
- return SingletonHolder.INSTANCE;
- }
- }
- /**
- * 静态内部类方式:反射方式破解单例的解决方法
- */
- public class Singleton {
- private static boolean flag = false;
-
- //私有构造方法
- private Singleton() {
- if (flag) {//如果是true,不是第一次创建
- throw new RuntimeException("不能创建多个对象");
- }
- flag = true;
- }
-
- private static volatile Singleton instance;
-
- //对外提供静态方法获取该对象
- public static Singleton getInstance() {
-
- if (instance != null) {
- return instance;
- }
-
- synchronized (Singleton.class) {
- if (instance != null) {
- return instance;
- }
- instance = new Singleton();
- return instance;
- }
- }
- }
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
-
- /**
- * 第二次用反射破坏单例模式
- */
- public class Test {
- public static void main(String[] args) throws Exception {
- //获取Singleton类的字节码对象
- Class c = Singleton.class;
- //获取Singleton类的私有无参构造方法对象
- Constructor constructor = c.getDeclaredConstructor();
- //取消访问检查
- constructor.setAccessible(true);
-
- //创建Singleton类的对象s1
- Singleton s1 = (Singleton) constructor.newInstance();
-
- //破坏单例
- Field flag = c.getDeclaredField("flag");
- flag.setAccessible(true);
- flag.set(s1, false);
-
- //创建Singleton类的对象s2
- Singleton s2 = (Singleton) constructor.newInstance();
-
- //判断通过反射创建的两个Singleton对象是否是同一个对象
- System.out.println(s1 == s2);//false
- }
- }