满纸荒唐言,一把辛酸泪,都云作者痴,谁解其中味,都是单例模式,很多次都是死在这个模式上,当然我指的是面试:今天可算是想好好研究下 --《单例模式》:
-
大家都知道的是,这个模式是最长用到的设计模式之一,熟悉设计模式的朋友们肯定不会陌生,其实我刚开始也是不清楚单例是什么?之前也是看过几篇文章有些模糊的认识:单例模式呐?是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在,而且自行实例化并向整个系统提供这个实例,一般来说在计算机系统中,线程池,缓存,日志对象,对话框,打印机,显卡的驱动程序对象都被设置成单例模式,这些应用或多或少都拥有资源管理器的功效。
-
单例模式的特点:单例模式全局只能有一个实例
-
单例类必须自己创建自己唯一实例
-
单例类必须给所有其他对象提供这一实例
-
(单例模式必须有一个实例,还必须自己创建一个实例,还需要把这个实例提供给所有对象),当然了,单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要保证单例的一致性。
-
还有我们一直关注的线程安全问题,一方面在获取单例的时候,要保证不能产生多实例对象,另一方面,在使用单例对象时候,要注意单例对象内的实例变量是会被多线程共享的,推荐使用无状态的对象,不回因为多个线程交互而影线本身状态导致线程不安全,比如我们常用的VO,DTD等,局部变量是在用户栈中的,而且用户栈本身就是程序私有化内存区域,所以不存在线程安全问题)。
-
单例实现的方式:
public class Singleton(){ //饿汉式
private Singletin(){} //私有构造方法
private static Singleton single =new Singleton1();
//静态工厂方法
public static Singleton1 getInstance(){
return single;
}
}
饿汉式单例在类加载初始化的时候就创建好一个静态的对象供外部使用,Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机的范围内,Singleton的唯一实例只能通过getInstance()方法访问。
public class Singleton{
斜体样式 //先私有构造
private Singleton(){}
private static Singleton single =null;
public static Singleton getInstance(){
if(single ==null){
single =nuw Singleton();
}
return single;
}
}
这个实例的话是实现了懒汉式单例,但在多线程的环境下会产生多个single对象,所以还是需要改造:
public class Singleton{
Private Singleton (){}
private static Singleton single =null;
public static Singleton getInstance(){
//注意这例使用synchronized同步锁
synchronized(Singleton.class){
if(single == null){
single =new Singleton();
}
}
returen single;
}
}
在这上面加上synchronized同步锁或者是同步代码块,对类加同步锁,虽然解决了多个实例问题,但是运行效率却比较低,就好比上厕所,这个人出来,下个人才能进去,所以说运行效率比较低下。 -
List item
public class Singleton {
private Singleton(){}
private static Singleton single = null;
//双重检索
public static Singleton getInstance(){
if(single == null){
synchronized (Singleton.class){
if(single == null){
single =new Singleton();
}
}
}
return single;
}
}
是用双重检查进行了优化,可以避免整个方法被锁掉的情况,只需要对需要锁的部分进行加锁,可以提高效率。
public class Singleton{
//老规矩,私有化构造
private Singleton(){}
//静态内部类
private static class InnerObject{
private static Singleton single =new Singleton();
}
public static Singleton getInstance(){
return InnerObject.single;
}
}
静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化的对象时,默认的方式运行的到的结果就是多例的,所以还是需要注意的。
public class Singleton{
private Singleton(){}
private static Singleton single =null;
static {
single = new Singleton();
}
public static Singleton getInstance(){
return single;
}
}
内部枚举(美剧)类
public class SingletonFactou{
private enum EnmuSingleton{
Singleton;
private Singleton singleton;
private EnmuSingleton (){
singleton =new Singleton();
}
public Singleton getInstance(){
return sginleton;
}
}
public static Singleton getInstance(){
return EnmuSingleton.Singleton.getInstance();
}
}
class Singleton{
public Singleton(){}
}