设计模式之单例模式
来源:互联网 发布:linux stage2存放在哪 编辑:程序博客网 时间:2024/05/16 17:54
1、定义:
一个类有且仅有一个实例,并且自行实例化向整个系统提供(参见百度百科解释)。是一种常用的设计模式。例如Windows中的任务管理器只能打开一个;一个系统可以有多个打印任务,但是只能有一个正在工作的任务;一个系统中只能有一个ID生成器或计时器……
2、特点:
(1)该类中只能有一个实例;
(2)必须自行创建这个实例;
(3)必须向系统提供一个可以访问该实例的方法;
3、实现角度:
(1)该类提供私有的构造函数;
(2)类的定义中含有该类的私有、静态的对象;
(3)该类中含有共有、静态的方法或函数来获取或创建该类本身私有、静态的对象;
4、形式:
懒汉式、饿汉式、登记式单例
(一)懒汉式单例模式(延迟加载)
public class SingletonDemo { // 该模式在第一次调用时即被实例化 private SingletonDemo () {} // 私有的构造函数 private static SingletonDemo single=null; // 该类的私有、静态的对象 public static SingletonDemo getInstance() { // 共有、静态的方法以获取该类私有、静态的对象 if (single == null) { single = new SingletonDemo(); } return single; }
单线程下访问该实例,此实现方式是没问题的,参见代码:
public class ThreadSingletonTest {public static void main(String[] args) {SingletonDemo single1=SingletonDemo.getInstance();SingletonDemo single2=SingletonDemo.getInstance();assert single1==single2;}}多线程下并发访问该单例,则存在线程安全问题,参见代码:
public class ThreadTest implements Runnable { //存放单例对象,Set可避免存放重复元素 public Set<SingletonDemo> singles = new HashSet<SingletonDemo>(); @Override public void run() { //获取单例 SingletonDemo s = SingletonDemo.getInstance(); //添加单例 singles.add(s); } }
public class ThreadSingletonTest {public static void main(String[] args) {//SingletonDemo single1=SingletonDemo.getInstance();//SingletonDemo single2=SingletonDemo.getInstance();//assert single1==single2; ThreadTest t = new ThreadTest(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); System.out.println(t.singles); }}输出结果为[com.fan.testDemo.SingletonDemo@66505655]或com.fan.testDemo.SingletonDemo@1e9f2094……。由此可见多线程下访问的不是单例,存在线程安全问题。
解决方式:
(一)在getInstance方法前加上线程同步
public class SingletonDemo {private SingletonDemo(){}; private static SingletonDemo single=null; public static synchronized SingletonDemo getInstance(){ if(single==null){single=new SingletonDemo();}return single;}}
此方式线程每次访问实例均需要判断锁,效率较低,故采用方式二
(二)双重锁结构
public class SingletonDemo {private SingletonDemo(){}; private static SingletonDemo single=null; public static SingletonDemo getInstance(){ // 如果前面的线程获取了单例对象,则后面的线程就不用访问锁了(不进同步代码块)synchronized (SingletonDemo.class) { // 同步代码块使用的是该单例的的字节码文件对象if(single==null){single=new SingletonDemo();}return single;}}}
(三)静态内部类
public class SingletonDemo { private static class InnerClass{ private static final SingletonDemo single= new SingletonDemo(); } private SingletonDemo (){} public static final SingletonDemo getInstance() { return InnerClass.single; } }此方式较好。
(二)饿汉式单例模式
//饿汉式单例在类初始化时,单例对象已经自行实例化 public class SingletonTest {private SingletonTest(){};private static SingletonTest singletonTest=new SingletonTest();public static SingletonTest getInstance(){return singletonTest;}}
由于在 类加载时就已经完成了实例化的静态对象以供调用,所以毫无疑问是线程安全的。
(三)登记式单例模式
因为登记式单例模式在平时使用的极少,本人接触的较少,这里忽略。详情可以参考http://blog.csdn.net/lanzhizhuxia/article/details/7922977
(四)懒汉式和饿汉式异同
1 0
- 设计模式之 单例设计模式
- 设计模式之 单例设计模式
- 设计模式之单例设计模式
- 设计模式之-----------单例设计模式
- 设计模式之:单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之单例设计模式
- 设计模式之-单例设计模式
- 设计模式之单例设计模式 标签: 设计模式
- 设计模式之单例
- 设计模式之单例
- 设计模式之 单例
- Part02
- Ubuntu 上不了网
- 选择排序-JAVA
- 居中方法总结
- Thinkphp MVC以及4种url放文方式
- 设计模式之单例模式
- java汉诺塔问题
- 第七届蓝桥杯JAVA语言B组_分小组
- find使用小结
- maven提示错误,unresolved plugin解决方案
- Part03
- 蓝桥杯
- 蓝桥杯☆☆难度题目(8,9题)
- Part04