单例模式精讲
2018-10-03 17:58:05来源:博客园 阅读 ()
单例模式是一种创建性模式,是一种创建对象的方式,主要指的就是一个类在整个程序的运行的过程中对象只会创建一个实例,就是只会被new一次,然后下次访问这个对象的时候是不用重新创建对象的。官方的解释是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式有很多种写法,比如:懒汉式(线程安全/线程不安全)、饿汉式、枚举式、序列化式、内部类式、注册式、注册登记式、双重检查锁(DCL)等等。
下面使用穷举法举几个例子:
1.spring源码中的单例,可以使用getBean返回不同的对象。
2.咱们程序里面多线程同时操作一个txt文件时会出现错误,这个文件的创建可能是一个单例。
3.还有比如太阳、月亮、人等等应该也是可以说成是单例的,因为对象只有一个,所有人看到的是同一个太阳、月亮。
4.还有日常生活中的日历。
饿汉式
package pattern.single; public class Hungry { private Hungry(){ } private static final Hungry hungry=new Hungry(); public static Hungry getInstance(){ return hungry; } }
package pattern.single; public class SingleTest { public static void main(String[] args) { Hungry hungry=Hungry.getInstance(); Hungry hungry1=Hungry.getInstance(); System.out.println(hungry==hungry1); } }
饿汉式的优点是性能比较高,没有现成安全问题,还是对象在初始化的时候就已经创建,不管会不会用到都得创建,所以会有浪费资源。
懒汉式线程不安全
package pattern.single; public class LazyOne { private LazyOne(){} private static LazyOne lazy=null; public static LazyOne getInstance(){ if(lazy==null){ lazy=new LazyOne(); } return lazy; } }
package pattern.single; public class SingleTest { public static void main(String[] args) { LazyOne lazyOne=LazyOne.getInstance(); System.out.println(lazyOne); } }
这种方法只能在单线程的环境下使用,在多线程情况下存在线程安全问题,但是只会在用到的时候创建对象。
懒汉式线程安全
package pattern.single; public class LazyTwo { private LazyTwo(){} private static LazyTwo lazy=null; public static synchronized LazyTwo getInstance(){ if(lazy==null){ lazy=new LazyTwo(); } return lazy; } }
package pattern.single; public class SingleTest { public static void main(String[] args) { LazyTwo lazyTwo=LazyTwo.getInstance(); System.out.println(lazyTwo); } }
登记式\静态内部类
package pattern.single; public class LazyThree { private static boolean initialized=false; public LazyThree(){ synchronized (LazyThree.class){ if(initialized==false){ initialized=!initialized; }else{ throw new RuntimeException("单例被攻击"); } } } public static final LazyThree getInstance(){ return LazyHolder.Lazy; } private static class LazyHolder{ private final static LazyThree Lazy=new LazyThree(); } }
package pattern.single; public class SingleTest { public static void main(String[] args) { LazyThree lazyThree=LazyThree.getInstance(); System.out.println(lazyThree); } }
这种方式的效率比懒汉式线程安全的模式更高,同时在初始化的时候也不会加载,避免了资源的浪费。
枚举式
package pattern.single; public enum RegisterEnum { BLOCK(){ private int r=0; private int g=0; private int b=0; },RED(){ private int r=255; private int g=0; private int b=0; }; }
package pattern.single; public class SingleTest { public static void main(String[] args) { RegisterEnum registerEnum=RegisterEnum.BLOCK; System.out.println(registerEnum); } }
序列化式
package pattern.single; import java.io.Serializable; public class Seriable implements Serializable { public final static Seriable INSTANCE=new Seriable(); private Seriable(){} public static Seriable getInstance(){ return INSTANCE; } private Object readObject(){ return INSTANCE; } }
package pattern.single; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SingleTest { public static void main(String[] args) { Seriable s1 = null; Seriable s2 = Seriable.getInstance(); FileOutputStream fos = null; try { fos = new FileOutputStream("obj"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(s2); oos.flush(); oos.close(); FileInputStream fis = new FileInputStream("obj"); ObjectInputStream ois = new ObjectInputStream(fis); s1 = (Seriable)ois.readObject(); ois.close(); System.out.println(s1); System.out.println(s2); System.out.println(s1 == s2); } catch (Exception e) { e.printStackTrace(); } } }
注册式
package pattern.single; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class BeanFactory { private BeanFactory(){} private static Map<String,Object> ioc=new ConcurrentHashMap<>(); public static Object getBean(String className) throws Exception { if(ioc.containsKey(className)){ return ioc.get(className); }else{ ioc.put(className,Class.forName(className).newInstance()); } return ioc.get(className); } }
package pattern.single; public class SingleTest { public static void main(String[] args) { Object obj=BeanFactory.getBean("xxx.yyy");
System.out.println(obj);
}
}
双重检查锁(DCL)
package pattern.single; public class Singleton { private volatile static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ synchronized (Singleton.class){ if(singleton==null){ singleton=new Singleton(); } } } return singleton; } }
package pattern.single; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SingleTest { public static void main(String[] args) { Object obj=Singleton.getInstance(); System.out.println(obj); } }
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:JAVA方法直接用类名.的理解
- 设计模式-委派/策略模式 2020-06-09
- 深入理解:设计模式中的七大设计原则 2020-06-07
- 设计模式---类之间的关系知多少 2020-06-07
- 你与面试官所了解的单例模式并不一样! 2020-06-06
- 高手眼中的观察者模式有什么不一样 2020-06-05
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash