码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式-单例模式

时间:2019-10-01 10:08:40      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:contex   看到了   int   etc   用户体验   优化   单例对象   nts   ioc   

定义

单例模式 : 确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。

应用场景

J2EE标准中,ServletContext\ServletContextConfig等。

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()

方法。

设计模式-单例模式

标签:contex   看到了   int   etc   用户体验   优化   单例对象   nts   ioc   

原文地址:https://www.cnblogs.com/yintingting/p/11614575.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!