zoukankan      html  css  js  c++  java
  • 单例模式

     

    1.

    //饿汉式单例
    // 它是在类加载的时候就立即初始化,并且创建单例对象
    
        //优点:没有加任何的锁、执行效率比较高,
        //在用户体验上来说,比懒汉式更好
    
        //缺点:类加载的时候就初始化,不管你用还是不用,我都占着空间
        //浪费了内存,有可能占着茅坑不拉屎
    
        //绝对线程安全,在线程还没出现以前就是实例化了,不可能存在访问安全问题
    public class HungrySingleton {
        //先静态、后动态
        //先属性、后方法
        //先上后下
        private static final HungrySingleton hungrySingleton = new HungrySingleton();
    
        private HungrySingleton(){}
    
        public static HungrySingleton getInstance(){
            return  hungrySingleton;
        }
    }
    
    //饿汉式静态块单例
    public class HungryStaticSingleton {
        private static final HungryStaticSingleton hungrySingleton;
        static {
            hungrySingleton = new HungryStaticSingleton();
        }
        private HungryStaticSingleton(){}
        public static HungryStaticSingleton getInstance(){
            return  hungrySingleton;
        }
    }
    

    test

    public class ConcurrentExecutor {
        /**
         * @param runHandler
         * @param executeCount 发起请求总数
         * @param concurrentCount 同时并发执行的线程数
         * @throws Exception
         */
        public static void execute(final RunHandler runHandler,int executeCount,int concurrentCount) throws Exception {
            ExecutorService executorService = Executors.newCachedThreadPool();
            //控制信号量,此处用于控制并发的线程数
            final Semaphore semaphore = new Semaphore(concurrentCount);
            //闭锁,可实现计数量递减
            final CountDownLatch countDownLatch = new CountDownLatch(executeCount);
            for (int i = 0; i < executeCount; i ++){
                executorService.execute(new Runnable() {
                    public void run() {
                        try{
                            //执行此方法用于获取执行许可,当总计未释放的许可数不超过executeCount时,
                            //则允许同性,否则线程阻塞等待,知道获取到许可
                            semaphore.acquire();
                            runHandler.handler();
                            //释放许可
                            semaphore.release();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                        countDownLatch.countDown();
                    }
                });
            }
            countDownLatch.await();//线程阻塞,知道闭锁值为0时,阻塞才释放,继续往下执行
            executorService.shutdown();
        }
        public interface RunHandler{
            void handler();
        }
    }
    

    2.

    public class LazyDoubleCheckSingleton {
        private volatile static LazyDoubleCheckSingleton lazy = null;
    
        private LazyDoubleCheckSingleton(){}
        public static LazyDoubleCheckSingleton getInstance(){
            if(lazy == null){
                synchronized (LazyDoubleCheckSingleton.class){
                    if(lazy == null){
                        lazy = new LazyDoubleCheckSingleton();
                        //1.分配内存给这个对象
                        //2.初始化对象
                        //3.设置lazy指向刚分配的内存地址
                        //4.初次访问对象
                    }
                }
            }
            return lazy;
        }
    }
    

     test

    //懒汉式单例
    
    
    //这种形式兼顾饿汉式的内存浪费,也兼顾synchronized性能问题
    //完美地屏蔽了这两个缺点
    //史上最牛B的单例模式的实现方式
    public class LazyInnerClassSingleton {
        //默认使用LazyInnerClassGeneral的时候,会先初始化内部类
        //如果没使用的话,内部类是不加载的
        private LazyInnerClassSingleton(){
            if(LazyHolder.LAZY != null){
                throw new RuntimeException("不允许创建多个实例");
            }
        }
    
        //每一个关键字都不是多余的
        //static 是为了使单例的空间共享
        //保证这个方法不会被重写,重载
        public static final LazyInnerClassSingleton getInstance(){
            //在返回结果以前,一定会先加载内部类
            return LazyHolder.LAZY;
        }
    
        //默认不加载
        private static class LazyHolder{
            private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
        }
    }
    

     test

    public class LazyInnerClassSingletonTest {
    
        public static void main(String[] args) {
            try{
                //很无聊的情况下,进行破坏
                Class<?> clazz = LazyInnerClassSingleton.class;
    
                //通过反射拿到私有的构造方法
                Constructor c = clazz.getDeclaredConstructor(null);
                //强制访问,强吻,不愿意也要吻
                c.setAccessible(true);
    
                //暴力初始化
                Object o1 = c.newInstance();
    
                //调用了两次构造方法,相当于new了两次
                //犯了原则性问题,
                Object o2 = c.newInstance();
    
                System.out.println(o1 == o2);
    //            Object o2 = c.newInstance();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    //懒汉式单例
    //在外部需要使用的时候才进行实例化
    public class LazySimpleSingleton {
        private LazySimpleSingleton(){}
        //静态块,公共内存区域
        private static LazySimpleSingleton lazy = null;
        public synchronized static LazySimpleSingleton getInstance(){
            if(lazy == null){
                lazy = new LazySimpleSingleton();
            }
            return lazy;
        }
    }
    

    test

    public class ExectorThread implements Runnable{
        @Override
        public void run() {
            LazySimpleSingleton singleton = LazySimpleSingleton.getInstance();
    //        ThreadLocalSingleton singleton = ThreadLocalSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + ":" + singleton);
        }
    }
    
    public class LazySimpleSingletonTest {
        public static void main(String[] args) {
            Thread t1 = new Thread(new ExectorThread());
            Thread t2 = new Thread(new ExectorThread());
            t1.start();
            t2.start();
            System.out.println("End");
        }
    }
    

     3.

    //Spring中的做法,就是用这种注册式单例
    public class ContainerSingleton {
        private ContainerSingleton(){}
        private static Map<String,Object> ioc = new ConcurrentHashMap<String,Object>();
        public static Object getInstance(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);
                }
            }
        }
    }
    
    //常量中去使用,常量不就是用来大家都能够共用吗?
    //通常在通用API中使用
    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;
        }
    }
    

    test 

    public class EnumSingletonTest {
    //    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();
    //        }
    //    }
    
    
        public static void main(String[] args) {
            try {
                Class clazz = EnumSingleton.class;
                Constructor c = clazz.getDeclaredConstructor(String.class,int.class);
                c.setAccessible(true);
                EnumSingleton enumSingleton = (EnumSingleton)c.newInstance("Tom",666);
    
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
    }
    

    4.

    //反序列化时导致单例破坏
    public class SeriableSingleton implements Serializable {
    
        //序列化就是说把内存中的状态通过转换成字节码的形式
        //从而转换一个IO流,写入到其他地方(可以是磁盘、网络IO)
        //内存中状态给永久保存下来了
    
        //反序列化
        //讲已经持久化的字节码内容,转换为IO流
        //通过IO流的读取,进而将读取的内容转换为Java对象
        //在转换过程中会重新创建对象new
    
        public  final static SeriableSingleton INSTANCE = new SeriableSingleton();
        private SeriableSingleton(){}
    
        public static SeriableSingleton getInstance(){
            return INSTANCE;
        }
    
        private  Object readResolve(){
            return  INSTANCE;
        }
    
    }
    

    test

    public class SeriableSingletonTest {
        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();
            }
        }
    }
    

    5.

    public class ThreadLocalSingleton {
        private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance =
                new ThreadLocal<ThreadLocalSingleton>(){
                    @Override
                    protected ThreadLocalSingleton initialValue() {
                        return new ThreadLocalSingleton();
                    }
                };
    
        private ThreadLocalSingleton(){}
    
        public static ThreadLocalSingleton getInstance(){
            return threadLocalInstance.get();
        }
    }
    

     test

    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());
            System.out.println(ThreadLocalSingleton.getInstance());
    
            Thread t1 = new Thread(new ExectorThread());
            Thread t2 = new Thread(new ExectorThread());
            t1.start();
            t2.start();
            System.out.println("End");
    
        }
    }
    

     6.

    public class Pojo {
    }
    public class ContainerSingletonTest {
        public static void main(String[] args) {
    
    
            try {
                long start = System.currentTimeMillis();
                ConcurrentExecutor.execute(new ConcurrentExecutor.RunHandler() {
                    public void handler() {
                        Object obj = ContainerSingleton.getInstance("com.gupaoedu.vip.pattern.singleton.test.Pojo");;
                        System.out.println(System.currentTimeMillis() + ": " + obj);
                    }
                }, 10,6);
                long end = System.currentTimeMillis();
                System.out.println("总耗时:" + (end - start) + " ms.");
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    }
    
  • 相关阅读:
    ajax 新闻栏目
    ajax 瀑布流实现
    html5 canvas图片渐变
    html5 canvas图片翻转
    html5 canvas图片反色
    ajax 第一个程序
    ajax 新闻栏目
    HDU 1756 Cupid's Arrow( 判断点在多边形的内外 )
    POJ 2356 Find a multiple( 鸽巢定理简单题 )
    HDU 5762 Teacher Bo ( 暴力 )
  • 原文地址:https://www.cnblogs.com/flgb/p/10549868.html
Copyright © 2011-2022 走看看