美仑美家具的网站谁做的,二维码网页制作免费网站制作,网站seo规划,网站规划的一般步骤什么是单例模式#xff1f;单例模式是一种常见的设计模式#xff0c;单例模式的写法有很多种#xff0c;这里主要介绍三种#xff1a; 懒汉式单例模式、饿汉式单例模式、登记式单例 。单例模式有以下特点#xff1a;1、单例类只能有一个实例。2、单例类必须自己创建自己唯…什么是单例模式单例模式是一种常见的设计模式单例模式的写法有很多种这里主要介绍三种 懒汉式单例模式、饿汉式单例模式、登记式单例 。单例模式有以下特点1、单例类只能有一个实例。2、单例类必须自己创建自己唯一的实例。3、单例类必须给所有其它对象提供这一实例。单例模式确保某各类只有一个实例而且自行实例化并向整个系统提供这个实例。在计算机系统中线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能每台计算机可以有若干个打印机但只能有一个Printer spooler以避免两个打印作业同时输出到打印机中每台计算机可以有若干通信端口系统应当集中管理这些通信端口以避免一个通信端口同时被两个请求同时调用。总之选择单例模式就是为了避免不一致状态.在将单例之前要做一次基础知识的科普行动大家都知道Java类加载器加载内容的顺序1、从上往下(Java的变量需要声明才能使用)2、先静态后动态(对象实例化) (静态块和static关键字修饰在实例化以前分配内存空间)3、先属性后方法(成员变量不能定义在方法中只能定义在class下)懒汉式单例(4种写法)懒汉式顾名思义需要用到的时候才会初始化饿汉式不管用不用先实例化注册登记式相当于有一个容器装载实例在实例产生之前会先检查一下容器看有没有如果有就直接取出来使用如果没有就先new一个放进去然后在后面的人使用Spring IOC就是一种典型的注册登记单例第一种写法/*** Created by xingyuchao on 2018/1/20.* 懒汉式单例类在第一次使用的时候实例化自己*/public class Singleton {//1.第一步先将构造方法私有化private Singleton(){}//2.然后声明一个静态变量保存单例的引用private static Singleton single null;//3.通过提供一个静态方法来获得单例的引用public static Singleton getInstance(){if(single null){single new Singleton();}return single;}}Singleton1通过将构造方法限定为private避免了类在外部被实例化在同一个虚拟机范围内Signleton1的唯一实例只能通过getInstance()方法访问。事实上通过Java反射机制是能否实现实例化构造方法为private的类的那基本上会使所有的Java单例实现失效此问题在此处不做讨论但是以上懒汉式单例的实现没有考虑线程安全问题它是非线程安全的并发环境下可能出现多个Singleton1实例要实现线程安全有以下三种方式都是对getInstance这个方法的改造保证了懒汉式单例的线程安全.第二种写法在getInstance()方法上加同步/*** Created by xingyuchao on 2018/1/29.* 懒汉式单例类,保证线程安全*/public class Singleton2 {//1.第一步先将构造方法私有化private Singleton2(){}//2.然后声明一个静态变量保存单例的引用private static Singleton2 single null;//3.通过提供一个静态方法来获得单例的引用// 为了保证线程环境下正确访问给方法上加上同步锁synchronizedpublic static synchronized Singleton2 getInstance(){if(single null){single new Singleton2();}return single;}}第三种写法双重检测机制/*** Created by xingyuchao on 2018/1/29.* 懒汉式单例类,保证线程安全 双重检测机制*/public class Singleton3 {//1.第一步先将构造方法私有化private Singleton3(){}//2.然后声明一个静态变量保存单例的引用private static Singleton3 single null;//3.通过提供一个静态方法来获得单例的引用// 为了保证线程环境下的另一种实现方式双重锁检查public static synchronized Singleton3 getInstance(){if(single null){single new Singleton3();}return single;}}第四种静态内部类/*** Created by xingyuchao on 2018/1/29.* 懒汉式单例类,通过静态内部类实现*/public class Singleton4 {//1. 先声明一个静态内部类//内部类的初始化需要依赖主类//也就是说当JVM加载Singleton4类的时候LazyHolder类也会被加载//只是目前还没有被实例化需要等主类先实例化后内部类才开始实例化private static class LazyHolder{//final是为了防止内部类将这个属性值覆盖掉private static final Singleton4 INSTANCE new Singleton4();}//2. 将默认构造方法私有化private Singleton4(){}//3.同样提供静态方法获取实例//当getInstance方法第一次被调用的时候它第一次读取LazyHolder.INSTANCE内部类LazyHolder类得到初始化// 而这个类在装载并被初始化的时候会初始化它的静态域从而创建Singleton4的实例由于是静态的域因此只会在// 虚拟机装载类的时候初始化一次并由虚拟机来保证它的线程安全性。这个模式的优势在于getInstance方法并没有被同步// 并且只是执行一个域的访问因此延迟初始化并没有增加任何访问成本。//此处加final是为了防止子类重写父类方法public static final Singleton4 getInstance(){return LazyHolder.INSTANCE;}}饿汉式单例(1种写法)/*** Created by xingyuchao on 2018/1/29.* 饿汉式单例类在类初始化时已经自行初始化不会产生线程安全问题*/public class Singleton5 {//1.同样也是将默认构造方法私有化private Singleton5(){}//2.声明静态变量在类初始化之前就初始化变量将对象引用保存//相反的如果这个单例对象一直没使用那么内存空间也就被浪费掉了private static final Singleton5 singleton new Singleton5();//3.开放静态方法获取实例public static Singleton5 getSingleton(){return singleton;}}枚举式单例(1种写法)public class DBConnection {}/*** Created by xingyuchao on 2018/1/29.* 枚举式单例*/public enum Singleton6 {DATASOURCE;private DBConnection connection null;private Singleton6() {connection new DBConnection();}public DBConnection getConnection() {return connection;}}/*** Created by xingyuchao on 2018/1/29.*/public class Main {public static void main(String[] args) {DBConnection dbConnection1 Singleton6.DATASOURCE.getConnection();DBConnection dbConnection2 Singleton6.DATASOURCE.getConnection();System.out.println(dbConnection1 dbConnection2); //true true结果表明两次获取返回了相同的实例。}}这种方式不仅能避免多线程同步问题而且能防止反射创建新的对象可谓是很坚强的壁垒不过这种方式用的极少为什么枚举会满足线程安全、序列化等标准。参考http://blog..net/gavin_dyson/article/details/70832185登记注册式单例/*** Created by xingyuchao on 2018/1/29.* 登记式单例类似spring里面的方法将类名注册下次直接从里面获取** 登记式单例实际上维护了一组单例类的实例将这些实例存放在一个Map(登记簿)中对于已经登记过的实例则从Map直接获取对于没有登记的则先登记然后返回** 内部实现还是用的饿汉式单例因为其中的static方法块它的单例在被装载的时候就被实例化了*/public class Singleton7 {private static Map map new HashMap();static{Singleton7 singleton7 new Singleton7();map.put(singleton7.getClass().getName(),singleton7);}//保护的默认构造protected Singleton7(){}//静态工程方法返回此类的唯一实例public static Singleton7 getInstance(String name) throws Exception {if(name null){name Singleton7.class.getName();}if(map.get(name) null){map.put(name,(Singleton7)Class.forName(name).newInstance());}return map.get(name);}}测试public class Test {public static void main(String[] args) throws Exception{//启动100个线程同时去抢占cpu 有可能产生并发观察并发情况下是否为同一个对象实例int count 100;//发令枪CountDownLatch latch new CountDownLatch(count);for (int i 0; i count; i){//Lambda简化后new Thread(()-{System.out.println(System.currentTimeMillis() : Singleton4.getInstance());}).start();latch.countDown();}latch.await(); //开始法令抢占cpu}}结果分布式环境下的单例有两个问题需要注意1. 如果单例类由不同的类装载器装载那边可能存在多个单例类的实例。假定不是远端存取例如有一些servlet容器对每个servlet使用完全不同的类装载器这样的话如果有两个servlet访问一个单例类它们就会有各自的实例解决指定classloaderprivate static Class getClass(String classname) throws ClassNotFoundException{ClassLoader classloader Thread.currentThread().getContextClassLoader();if(classloader null){classloader Singleton.class.getClassLoader();}return (classloader.loadClass(classname));}2. 如果Singleton实现了java.io.Serializable接口那么这个类的实例就可能被序列化和复原。不管怎么样如果你序列化一个单例类的对象接下来复原多个那个对象那么就会有多个类的实例public class Singleton implements Serializable {public static Singleton singleton new Singleton();protected Singleton(){}private Object readResolve(){return singleton;}}