首页 > 代码库 > 设计模式-单例模式
设计模式-单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例,为什么做这种设计,有些现实服务中设备只有一个,不可能让一个设备同时去做相同的服务给多人,就需要单例模式进行控制了。
通常来说单例模式分为懒汉式与饿汉式,其中又有许多细节划分,不过我觉得很多东西多余初学者来说没有意义,只是随着时间的增长慢慢理解。
单例模式都是跟工厂模式结合的,通常来说都是工厂方法模式
单利模式创建遵循以下概念:
1,构造方法私有化
2,提供一个公开的方法获取类的实例
懒汉与饿汉的区别:
懒汉在需要调用实例的时候才会第一次创建,饿汉则在类加载时创建自身的实例。
懒汉:
懒汉式-多线程可能会出现创建多个实例
单例类 -
//懒汉 public class Singleton { private static Singleton singleton; public static Singleton getSingleton() { if (singleton == null) { singleton = new Singleton(); } return singleton; } public void print(){ System.out.println(singleton.hashCode()); } }
测试一下 ,通过打印hashcode 可以查看实例在内存中是否为同一个引用
创建一个线程类
public class Thread extends java.lang.Thread { @Override public void run(){ try { Singleton.getSingleton().print(); } catch (InterruptedException e) { e.printStackTrace(); } } }
来测试:
public class MainTest { public static void main(String[] args){ Thread thread;//这是上面的线程类 for (int num = 0; num<=100 ;num++) { thread= new Thread(); thread.start(); } } }
控制台打印:
控制台:
可以看出,单利模式已经成功了,所有线程在内存中都是调用的同一个实例的引用,可能因为cpu速率太快,每个线程都完整的跑完了,可这不是我要的效果。我要测试的是在在多线程情况下,可能创建多个实例的情况;
Thread.sleep(1000L)会让当前线程休眠一秒,并且不释放锁。
修改单例类:
public class Singleton { private static Singleton singleton; public static Singleton getSingleton() throws InterruptedException { if (singleton == null) { Thread.sleep(1000L);//休眠不释放锁,让其他线程进入,因为方法不是同步的,没有阻塞,所以其他方法也可以进入 singleton = new Singleton(); } return singleton; } public void print(){ System.out.println(singleton.hashCode()); } }
测试:
已经不能实现单例的需求
有一个方法就是加同步,来支持多线程操作
//懒汉-同步 public class Singleton { private static Singleton singleton; //加同步 public static synchronized Singleton getSingleton() { if (singleton == null) { singleton = new Singleton(); } return singleton; } public void print(){ System.out.println(singleton.hashCode()); } }
饿汉式:
饿汉现在有很多种写法,饿汉的实例是基于JVM在ClassLoader时创建的。ClassLoader在类加载时会验证静态代码块,基于此可以做实例化操作等
最简单的饿汉:
public class Singleton { private static Singleton singleton= new Singleton(); private Singleton (){} public static Singleton getSingleton() { return singleton; } }
不过现在最常用的写法
比较常用的写法0-双重校验写法:
//双重检验 public class Singleton { private volatile static Singleton singleton; private Singleton() { } //如果多线程情况下 public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { //多线程进入 线程1 进入此处 并有锁,此时未创建实例 另一个线程进入,无法获取锁,被阻塞 if (singleton == null) { //线程1 进入此处并创建实例 singleton = new Singleton(); } }//线程1创建实例并释放锁 ,然后线程2进入synchronized同步快,发现已经创建了实例 } return singleton; } }
设计模式-单例模式
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。