• 单例模式的各种写法和总结 懒汉式 饿汉式 登记式


    public class Singleton {//懒汉式单例类
    /**
     懒汉式单例类。   只在外部对象第一次请求实例的时候才会去创建
         优点:第一次调用时才会初始化,避免内存浪费。
        缺点:必须加锁synchronized 才能保证单例
     */
      private static volatile Singleton singleton;// !!必须要加volatile限制指令重排序,不然这是双重检验的漏洞
        private static final ReentrantLock lock = new ReentrantLock();
        private static AtomicInteger count=new AtomicInteger(0);
        private Singleton() {
            count.incrementAndGet();
        }
    
        public static synchronized  Singleton getInstance() {
        
            if (singleton == null) {
                lock.lock();
                if (singleton == null) { //双重锁定,防止几个线程同时进入,eg:a进入,bc等待,a第一次实例化单例,b得到锁后进入,
                                            //此处如不判断,则b也会实例化单例,造成多次实例化。 但是多线程测试中没出现这种情况
                    singleton = new Singleton();
                }
                lock.unlock();
            }
            return singleton;
        }
        public void show(){
            System.out.println(count);
        }
        
        public static void main(String[] args) throws InterruptedException {
    //        Singleton s1 = Singleton.getInstance();
    //        Singleton s2 = Singleton.getInstance();
    //        if (s1 == s2)
    //            System.out.println("euqal");//equal
    //        else {
    //            System.out.println("not equal");
    //        }
            
            ExecutorService service = Executors.newCachedThreadPool();
            for(int i=0;i<50;i++){
                Thread t =new Thread(new MyThread());
                service.execute(t);
            }
    
            Thread.sleep(5000);
            service.shutdown();
        }
    }
    
    class MyThread implements Runnable{
    
        @Override
        public void run() {
            Singleton s = Singleton.getInstance();
            s.show();
        }
        
    }

    饿汉式单例类

    public class SingletonHungry {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool();
        for(int i=0;i<30;i++){
            Thread t =new Thread(new MyThread2());
            service.execute(t);
        }
    
        Thread.sleep(1000);
        service.shutdown();
    }
    }
    /*
           饿汉式单例类。    它在类加载时就立即创建对象。
           优点:没有加锁,执行效率高。  用户体验上来说,比懒汉式要好。
            缺点:类加载时就初始化,浪费内存
     */
    class Singleton2{
        private static AtomicInteger count = new AtomicInteger(10);
        private static final Singleton2 SINGLETON = new Singleton2();
        private Singleton2(){
            count.incrementAndGet();
        }
        public static Singleton2 getInstance(){
            return SINGLETON;
        }
        public void show() {
            System.out.println(count);
        }
    }
    class MyThread2 implements Runnable{
    
        @Override
        public void run() {
            Singleton2 s2 = Singleton2.getInstance();
            s2.show();
        }
        
    }

    登记式模式

    内部类只有在外部类被调用才加载,产生SINGLETON实例,又不用加锁,此模式有上述俩模式的优点,屏蔽了他们的缺点,是最好的单例模式。
    public class Singleton{
        private Singleton(){}
        public static Singleton getInstance(){ return Holder.SINGLETON;}
        private static class Holder{//内部类
            private static final Singleton SINGLETON= new Singleton();
        }
    }
    单例类的特点:
    1、单例类确保自己只有一个实例
    2、单例类必须自己创建自己的实例
    3、单例类必须为其他对象提供唯一的实例。

    单例类的优点:

    (1) 控制资源的使用,通过线程同步来控制资源的并发访问。
    (2)控制实例的产生数量,达到节约资源的目的。
    (3)作为通信的媒介,数据共享。他可以在不建立直接关联的条件下,让多个不相关的两个线程或者多个进程之间实现通信。

    单例类实用举例:Windows的任务管理器,打不开两个。 网站的计数器,不然很难实现同步。   数据库连接池的设计

  • 相关阅读:
    Linux_C smsh1
    ACM&排序问题,操作符重载
    ACM&找双亲,并查集
    struct dirent/DIR
    关于win8如何查找出当前的密钥
    php之留言板
    php之include&require
    工作中的问题 和 所用到的知识点
    jQuery.extend 和 jQuery.fn.extend
    JavaScript 字符串函数 之查找字符方法(一)
  • 原文地址:https://www.cnblogs.com/todayjust/p/5810202.html
Copyright © 2020-2023  润新知