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

    简单介绍

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    单例模式有以下特点: 

     1、单例类只能有一个实例。 

     2、单例类必须自己创建自己的唯一实例。 

     3、单例类必须给所有其他对象提供这一实例。 

     单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

    一、懒汉式单例

    package wbg;
    
    import com.Thr;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Test {
        public static void main(String[] args) {
            ExecutorService ex= Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
               ex.execute(new Runnable() {
                   @Override
                   public void run() {
                       Boss boss=Boss.getInstance();
                       System.out.println(boss);
                   }
               });
    
            }
    
        }
    }
    class Boss {
        private Boss(){};
        private  static  Boss boss=null;
        public static Boss getInstance() {
            if (boss == null) {
                boss = new Boss();
            }
            return boss;
        }
    }
    View Code

    运行结果(多次运行)

    Boos通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Boss的唯一实例只能通过getInstance()方法访问。

    (事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

    以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全

    1、在getInstance方法上加同步

    package wbg;
    
    import com.Thr;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Test {
        public static void main(String[] args) {
            ExecutorService ex= Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
               ex.execute(new Runnable() {
                   @Override
                   public void run() {
                       Boss boss=Boss.getInstance();
                       System.out.println(boss);
                   }
               });
    
            }
    
        }
    }
    class Boss {
        private Boss(){};
        private  static  Boss boss=null;
        public synchronized static Boss getInstance() {
            if (boss == null) {
                boss = new Boss();
            }
            return boss;
        }
    }
    View Code

    运行结果

    2、双重检查锁定

    package wbg;
    
    import com.Thr;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Test {
        public static void main(String[] args) {
            ExecutorService ex= Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
               ex.execute(new Runnable() {
                   @Override
                   public void run() {
                       Boss boss=Boss.getInstance();
                       System.out.println(boss);
                   }
               });
    
            }
    
        }
    }
    class Boss {
        private Boss(){};
        private  static  Boss boss=null;
        public  static Boss getInstance() {
            if (boss == null) {
                synchronized(Boss.class){
                    if (boss == null) {
                        boss = new Boss();
                    }
                }
            }
            return boss;
        }
    }
    View Code

    运行结果

    3、静态内部类

    package wbg;
    
    import com.Thr;
    
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Test {
        public static void main(String[] args) {
            ExecutorService ex= Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
               ex.execute(new Runnable() {
                   @Override
                   public void run() {
                       Boss boss=Boss.getInstance();
                       System.out.println(boss);
                   }
               });
    
            }
    
        }
    }
     class Boss {
        static class LazyHolder{
            private static final Boss inst=new Boss();
        }
        private Boss(){};
        public static final Boss getInstance(){
            return LazyHolder.inst;
        }
     }
    View Code

    运行结果

     这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。

     详细:http://www.iteye.com/topic/652440

    volatile关键字

    package wbg;
    public class Boss {
        String name;
        String sex;
        Float money;
        //初始化一个静态变量
        private  static volatile Boss boss=null;
        //设置为私有
        private  Boss() {
        }
        //构造一个静态方法,通过它初始化或返还对象
        public static Boss getBoss(){
            //双重检查所机制
            if(boss==null){
                synchronized(Boss.class){
                    if(boss==null){
                        boss=new Boss();
                    }
                }
            }
            return boss;
        }
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Float getMoney() {
            return money;
        }
    
        public void setMoney(Float money) {
            this.money = money;
        }
    }

    volatile关键字详细:http://www.cnblogs.com/dolphin0520/p/3920373.html

     

  • 相关阅读:
    linux命令
    常用正则表达式总结
    List集合对象根据字段排序
    IO字 节流/字符流 读取/写入文件
    Jquery广告浮动效果小案例
    拿到添加对象的id号方法
    Jquery省市区三级联动案例
    JAVA集合迭代遍历和特性介绍
    Listener监听器使用小案例
    java中用过滤器解决字符编码问题
  • 原文地址:https://www.cnblogs.com/weibanggang/p/9473671.html
Copyright © 2011-2022 走看看