设计模式-单例模式

1.饿汉式单例

2.懒汉式单例 

3.静态内部类单例

4.枚举式单例 

5.ThreadLocal线程单例

6.注册式单例 

1.饿汉式单例:

特点: 程序启动时即创建好对象

优: 没有线程安全的问题

缺点:在创建的对象数量较多时可能会创建很多的无用对象,浪费资源

package com.cultivator1.singleton.hungry;


public class HungrySingletion {
    
    private static final HungrySingletion HUNGRY_SINGLETION = new HungrySingletion();
    
    public HungrySingletion() {
    }
    
    public static HungrySingletion getInstance() {
        return HUNGRY_SINGLETION;
    }
}
public class HungrySingletionTest {
    public static void main(String[] args) {
        System.out.println(HungrySingletion.getInstance());
        System.out.println(HungrySingletion.getInstance());
    }
}

2.懒汉式单例 :

特点: 在需要时创建对象 

优: 因为在需要时才创建对象,所以消耗更少的资源

缺: 容易出现线程安全的问题(可能通过双重检查锁来避免资源浪费的同时,较少地影响效率)

简单单例

public class LazySingleton {
    
    private static LazySingleton lazySingleton;
    
    private LazySingleton() {
    }
    
    public static LazySingleton getInstance() {
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}
public class LazySingletonRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(LazySingleton.getInstance());
    }
}
public class LazySingletonTest {
    
    public static void main(String[] args) {
//        LazySingleton lazySingleton = LazySingleton.getInstance();
//        System.out.println(LazySingleton.getInstance());
//        System.out.println(LazySingleton.getInstance());
        Thread thread = new Thread(new LazySingletonRunnable());
        Thread thread2 = new Thread(new LazySingletonRunnable());
        Thread thread3 = new Thread(new LazySingletonRunnable());
        thread.start();
        thread2.start();
        thread3.start();
    }
}

双重检查锁单例

public class DoubleCheck {
    
    private static DoubleCheck doubleCheck;
    
    private DoubleCheck() {
    }
    
    public static DoubleCheck getInstance() {
        
        if (doubleCheck != null) {
            return doubleCheck;
        }
        synchronized (DoubleCheck.class) {
            if (doubleCheck != null) {
                return doubleCheck;
            }
            doubleCheck = new DoubleCheck();
            return doubleCheck;
        }
        
    }
}
public class DoubleCheckRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(DoubleCheck.getInstance());
    }
}
public class DoubleCheckTest {
    public static void main(String[] args) {
        
        Thread thread = new Thread(new DoubleCheckRunnable());
        Thread thread2 = new Thread(new DoubleCheckRunnable());
        Thread thread3 = new Thread(new DoubleCheckRunnable());
        thread.start();
        thread2.start();
        thread3.start();
        
    }
}

3.静态内部类单例: 

特点: 单例是内部类

优点: 调用内部类时才会创建对象,资源浪费少

缺: 容易被反射破坏(可能通过构造方法判断来避免)

public class InnerSingleton {
    
    private InnerSingleton() {
        if (InnerSingletonSub.INSTANCE != null) {
            throw new RuntimeException("单例对象不允许重复");
        }
    }
    
    public static InnerSingleton getInstance() {
        return InnerSingletonSub.INSTANCE;
    }
    
    /**
     * 外部类调用时会调用内部类, 一旦调用 new InnerSingleton(),会先调用这里,再new new
     * InnerSingleton(),所以反射也会报错
     */
    private static class InnerSingletonSub {
        
        private static final InnerSingleton INSTANCE = new InnerSingleton();
    }
    
}

public class InnerSingletonTread implements Runnable {
    @Override
    public void run() {
        System.out.println(InnerSingleton.getInstance());
        
    }
}
public class InnerSingletonTest {
    public static void main(String[] args) {
        try {
            Class clazz = InnerSingleton.class;
            Constructor constructor = clazz.getDeclaredConstructor(null);
            constructor.setAccessible(true);
            InnerSingleton innerSingleton = (InnerSingleton)constructor.newInstance();
            System.out.println("反射: " + innerSingleton);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        Thread thread = new Thread(new InnerSingletonTread());
        Thread thread2 = new Thread(new InnerSingletonTread());
        Thread thread3 = new Thread(new InnerSingletonTread());
        thread.start();
        thread2.start();
        thread3.start();

        
    }
}

注册式单例: 

特点:对象单例集中管理到一个注册中心

优: 对象集中管理,更加方便

缺: 调用也会相对复杂一些(可能用类的全路径来避免重复),有全程安全的问题(可以通过加锁解决)

public class ContainerSingleton {
    
    private static Map<String, Object> ioc = new ConcurrentHashMap<>();
    
    private ContainerSingleton() {
    }
    
    public static Object getInstance(String className) {
        
        try {
            if (!ioc.containsKey(className)) {
                synchronized (ioc) {
                    if (!ioc.containsKey(className)) {
                        ioc.put(className, Class.forName(className).newInstance());
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return ioc.get(className);
        
    }
}

public class ContainerSingletonThread implements Runnable {
    @Override
    public void run() {
        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
    }
}
public class ContainerSingletonTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new ContainerSingletonThread());
        Thread thread2 = new Thread(new ContainerSingletonThread());
        Thread thread3 = new Thread(new ContainerSingletonThread());
        thread.start();
        thread2.start();
        thread3.start();
        
//        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
//        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
//        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
    }
}

4.枚举式单例


特点: 运用枚举的方式创建单例
优点: 没有线程安全的问题
缺点: 在程序启动时即创建单例(本质上是一个饿汉式单例)

public enum EnumSingleton {
    
    INSTANCE;
    
    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}

public class EnumSingletonTest {
    public static void main(String[] args) {
        System.out.println(EnumSingleton.getInstance());
        System.out.println(EnumSingleton.getInstance());
        System.out.println(EnumSingleton.getInstance());
        System.out.println(EnumSingleton.getInstance());
        try {
            Constructor constructor = EnumSingleton.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            System.out.println(constructor.newInstance());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.线程单例 :

特点: 在单个线程中对象只有一个,适用于线程内的变量共享,例如多数据库切换,线程变量共享

public class ThreadLocalSingleton {
    private static ThreadLocal<ThreadLocalSingleton> threadLocal = new ThreadLocal<>();
    
    private ThreadLocalSingleton() {
    }
    
    public static ThreadLocalSingleton getInstance() {
        
        if (threadLocal.get() == null) {
            threadLocal.set(new ThreadLocalSingleton());
        }
        return threadLocal.get();
        
    }
}

public class ThreadLocalSingletonThread implements Runnable {
    @Override
    public void run() {
        System.out.println(ThreadLocalSingleton.getInstance());
    }
}
public class ThreadLocalSingletonTest {
    
    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());
        Thread thread = new Thread(new ThreadLocalSingletonThread());
        Thread thread2 = new Thread(new ThreadLocalSingletonThread());
        Thread thread3 = new Thread(new ThreadLocalSingletonThread());
        thread.start();
        thread2.start();
        thread3.start();
    }
}

6.注册式单例 : 

特点: 所有的对象都存在一个容器中

优点: 在需要时创建单例,

缺点: 都在同一个地方获取对象(可以在启动时判断下他们的唯一性,使用时再创建),有线程安全的问题(可以通过双重检查锁来避免,虽然ConcurrentHashMap通过锁分段技术避免了死锁的同时,提升了效率,但是无法避免对象添加时的重复创建对象的问题)

 
public class ContainerSingleton {
    
    private static Map<String, Object> ioc = new ConcurrentHashMap<>();
    
    private ContainerSingleton() {
    }
    
    public static Object getInstance(String className) {
        
        try {
            if (!ioc.containsKey(className)) {
                synchronized (ioc) {
                    if (!ioc.containsKey(className)) {
                        ioc.put(className, Class.forName(className).newInstance());
                    }
                }
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return ioc.get(className);
        
    }
}
public class ContainerSingletonThread implements Runnable {
    @Override
    public void run() {
        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
    }
}
public class ContainerSingletonTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new ContainerSingletonThread());
        Thread thread2 = new Thread(new ContainerSingletonThread());
        Thread thread3 = new Thread(new ContainerSingletonThread());
        thread.start();
        thread2.start();
        thread3.start();
        
//        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
//        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
//        System.out.println(ContainerSingleton.getInstance("com.cultivator1.singleton.container.ContainerSingletonTest"));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值