单例模式:程序中只能有一个实例对象,比如果线程池、数据库连接池等。
特点:整个程序中只能有一个实例对象
该类的实例对象只能由自己创建
该类提供一个外部访问方法可以得到这个实例对象
单例模式的写法:
第一种是最简单的写法,叫做懒汉式单例,在类初始化时没有创建了实例对象,只有在调用getInstance()方法时才会创建实例,这种写法在编写多线程程序时会造成线程非安全问题
public class LazySingleton{
private LazySingleton lazySingleton;
private LazySingleton(){} //private 修饰可以让该类在外面无法被实例化创建
public static LazySingleton getInstance(){
if(lazySingleton!=null){
return lazySingleton;
}else{
lazySingleton = new LazySingleton();
}
}
}
第二种写法是在第一种写法的基础上,通过添加关键字修饰符来使线程安全
在这里,我简单说一下volatile关键字,多个线程之间的可见性指的有A、B两个线程,都可以访问到共享常量a,在A线程改变共享常量a后,B线程可以立刻得到改变后的共享常量a的值。
这里需要理解一下,线程在执行过程中,他的数据读取并不是在主内存中,而是从主内存中拷贝一份数据到自己的工作内存中,之后从工作内存中读取数据,而在A线程改变了主内存中共享常量a的值后,B线程还是从他自己的工作内存中读取共享常量a,这样读不到最新的a。
public class LazySingleton{
volatile private LazySingleton lazySingleton;//添加volatile关键字解决变量在多线程之间的可见性
private LazySingleton(){} //private 修饰可以让该类在外面无法被实例化创建
synchronized public static LazySingleton getInstance(){//添加synchronized关键字解决了多线程之间访问资源的同步性
if(lazySingleton!=null){
return lazySingleton;
}else{
lazySingleton = new LazySingleton();
}
}
}
第三种写法,叫做饿汉式单例,在类加载时就创建实例对象供系统使用,是线程安全的,如果在接下来没有用到该类时,会造成内存资源浪费。
public class LazySingleton{
private LazySingleton lazySingleton = new LazySingleton();
private LazySingleton(){} //private 修饰可以让该类在外面无法被实例化创建
public static LazySingleton getInstance(){
return lazySingleton;
}
}