设计模式-单例模式
Posted yintingting
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-单例模式相关的知识,希望对你有一定的参考价值。
定义
单例模式 : 确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
应用场景
J2EE标准中,ServletContextServletContextConfig等。
spring中的AppliationContext
数据库的连接池
。。。。
实现方式
(1)饿汉式
特点:在类加载的时候就立即创建单例对象。绝对线程安全,因为在线程还未出现前就实例化了,不可能出现访问安全问题。
优点:没有加任何的锁,执行效率高,用户体验好
缺点:类加载的时候就初始化,不管是否使用到都占着空间,可能会造成内存浪费
例子:spring IOC容器ApplicationContext就是典型的饿汉式单例。
方式一:
public class HungrySingleton { //先静态、后动态 //先属性、后方法 //先上后下 private static final HungrySingleton hungrySingleton = new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){ return hungrySingleton; } }
方式二:
//饿汉式静态块单例 public class HungryStaticSingleton { private static final HungryStaticSingleton hungrySingleton; static { hungrySingleton = new HungryStaticSingleton(); } private HungryStaticSingleton(){} public static HungryStaticSingleton getInstance(){ return hungrySingleton; } }
(2)懒汉式
特点:被外部调用的时候才会实例化
//懒汉式单例 //在外部需要使用的时候才进行实例化 public class LazySimpleSingleton { private LazySimpleSingleton(){} //静态块,公共内存区域 private static LazySimpleSingleton lazy = null; public static LazySimpleSingleton getInstance(){ if(lazy == null){ lazy = new LazySimpleSingleton(); } return lazy; } }
public class ExectorThread implements Runnable{ @Override public void run() { LazySimpleSingleton singleton = LazySimpleSingleton.getInstance(); System.out.println(Thread.currentThread().getName() + ":" + singleton); } }
public class LazySimpleSingletonTest { public static void main(String[] args) { Thread t1 = new Thread(new ExectorThread()); Thread t2 = new Thread(new ExectorThread()); t1.start(); t2.start(); System.out.println("End"); } }
运行结果:
通过不断切换线程,并观测其内存状态,我们发现在线程环境下LazySimpleSingleton
被实例化了两次。有时,我们得到的运行结果可能是相同的两个对象,实际上是被后面
执行的线程覆盖了,我们看到了一个假象,线程安全隐患依旧存在。那么,我们如何来
优化代码,使得懒汉式单例在线程环境下安全呢?来看下面的代码,给getInstance()加
上synchronized 关键字,是这个方法变成线程同步方法:
public class LazySimpleSingleton { private LazySimpleSingleton(){} //静态块,公共内存区域 private static LazySimpleSingleton lazy = null; public synchronized static LazySimpleSingleton getInstance(){ if(lazy == null){ lazy = new LazySimpleSingleton(); } return lazy; } }
这时候,我们再来调试。当我们将其中一个线程执行并调用getInstance()方法时,另一
个线程在调用getInstance()方法,线程的状态由RUNNING 变成了MONITOR,出现阻
塞。直到第一个线程执行完,第二个线程才恢复RUNNING 状态继续调用getInstance()
方法。
以上是关于设计模式-单例模式的主要内容,如果未能解决你的问题,请参考以下文章