设计模式—singleton(单例模式)
程序员文章站
2021-12-19 19:19:03
单例模式 单例设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。 这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。 应用实例 Windows是多进程多线程的,通过唯一的实例来操作一个文 ......
单例模式
-
单例设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。
这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
应用实例
-
windows是多进程多线程的,通过唯一的实例来操作一个文件,避免地出现多个进程或线程同时操作一个文件的现象。
-
一些设备管理器常常设计为单例模式(如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件)。
使用场景
-
要求生产唯一序列号。
-
web 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
-
创建的一个对象需要消耗的资源过多,比如 i/o 与数据库的连接等。
单例实现
- 方式一
方式二
-
改进了方式一的缺点,但同时带来了线程安全问题
-
假设有两个线程,线程1到第9行判断完实例是否为空时(还没到new一个实例),线程2也到了判断实例是否为空的位置,
因为线程1还没创建实例,instance仍为空,线程2创建完一个实例后,线程1继续执行也创建了一个实例。
方式三
-
通过synchronized加锁,解决方式二的线程安全问题,但也带来了效率下降。
-
通过加锁,锁定了mgr03.class对象,因此输出的hashcode是相同的。
方式四
-
双重校验锁,完美的单例模式写法之一。
-
如果只有外层判断,就会出现线程安全问题(如同方式二)。
方式五
- 静态内部类方式,解决了方式一的问题,达到了按需初始化的目的,是完美的单例模式之一。
方式六
- 通过枚举实现单例
- 枚举方式
public class mgr05 { private mgr05() {}; //类mgr05加载时,内部类不会加载 private static class mgr05holder{ private final static mgr05 instance=new mgr05(); } //调用getinstance(),类mgr05holder加载 public static mgr05 getinstance() {return mgr05holder.instance;}; public static void main(string[] args) { for(int i=0;i<200;i++) { new thread(()->{ system.out.println(mgr05.getinstance().hashcode()); }).start(); } } }
public class mgr04 { private static volatile mgr04 instance; private mgr04() {}; public static synchronized mgr04 getinstance() { if(instance==null) {//双重校验锁 synchronized (mgr04.class) { if(instance==null) { try { thread.sleep(10); }catch(interruptedexception e) { e.printstacktrace(); } } } instance=new mgr04(); } return instance; } public void c() {system.out.println("c");} public static void main(string[] args) { for(int i=0;i<200;i++) { new thread(()->{ system.out.println(mgr04.getinstance().hashcode()); }).start(); } } }