1.单例模式原理
单例模式:确保一个类最多只有一个实例,并提供一个全局访问点。
代码示例:
public class Test {
public static class Abc
{
public Abc() {
};
}
public class Cbd
{
public Cbd()
{
Abc n1,n2;
n1=new Abc();
n2=new Abc();
}
}
public static void main(String[] args) {
Abc n1,n2;
n1=new Abc();
n2=new Abc();
System.out.println(n1+"~~~~~"+n2);
}
}
打印结果:
上边这个打印结果同时也反映了Cbd类中的构造方法内n1和n2的地址也是不同的,所以这种结构往往不能够实现单例。
代码示例对比:
public class Abc{
private Abc() { //私有化构造方法
};
......
}
如果一个类的构造方法使用private修饰,那么这个类就无法被这个类以外的其他类所实例化,通俗点讲就是在这个类以外的其他类中无法直接new这个类,同时就满足了类以外的其他类不会创建出这个类的多个类对象。那么要想创建这个类的实例只能让这个类自己实例化自己,通俗讲就是自己去new自己。
经典单例模式代码示例:
public class Singleton {
private static Singleton uniqeInstance=null;
private Singleton(){
};
public static Singleton getInstance(){
if(uniqeInstance==null){
uniqeInstance=new Singleton();
}
return uniqeInstance;
}
}
到这里单例模式的原理思想就讲完了。
2.单例模式
2.1懒汉式写法及线程安全优化写法
懒汉式顾名思义“比较懒”就是到了用的时候再去创建,用的时候才去检查有没有实例,如果有则返回,没有则新建。
懒汉式经典写法:
public class Singleton {
private static Singleton uniqeInstance=null;
private Singleton(){ //私有化构造方法
};
public static Singleton getInstance(){
if(uniqeInstance==null){ //判断实例是否存在,不存在则创建,否则直接返回
uniqeInstance=new Singleton();
}
return uniqeInstance;
}
}
弊端:多线程的情况下,假设该类还未实例化,两个线程同时进入了getInstance()方法,第一个线程进入了if代码块,在第一个线程正在创建但还未创建完该实例的时候,此时第二个线程也进入了if代码块,那么这时两个线程分别创建了该实例,即创建了两个实例。所以这种写法是非线程安全的。
懒汉式线程安全优化后写法:
public class Singleton {
private static Singleton uniqeInstance=null;
private Singleton(){ //私有化构造方法
};
public static synchronized Singleton getInstance(){
if(uniqeInstance==null)
{
uniqeInstance=new Singleton();
}
return uniqeInstance;
}
}
为了保证线程安全则在方法上边追加synchronized同步锁。
弊端:synchronized同步锁是非常消耗资源的。
2.2饿汉式
饿汉式不言而喻“比较勤”,不管是否使用实例,该实例都会在初始化时提前创建好,留作备用。
优点:无线程安全问题。
缺点:盲目创建浪费了资源。
private static Singleton uniqeInstance=new Singleton();
private Singleton(){ //私有化构造方法
};
public static Singleton getInstance(){
return uniqeInstance;
}
}
3.单例模式优化
3.1双重检查加锁(双检锁)
public class Singleton {
private volatile static Singleton uniqeInstance=null;
private Singleton(){ //私有化构造方法
};
public static Singleton getInstance(){
if(uniqeInstance==null){ //第一个判断,第一重检查
synchronized (Single.class) { //加锁
if(uniqeInstance==null){ //第二个判断,第二重检查
uniqeInstance=new Singleton();
}
}
}
return uniqeInstance;
}
}
假设对象还未实例化,多线问题像之前的那样,两个线程同时又进入了第一个if代码块,但是两个线程遇到synchronized ()方法,只有先拿到Single对象的线程才可以进入方法内部执行第二个if代码块。这样等Singleton对象被第一个线程实例化后,此后的所有线程将不再执行所有if内部的代码块,因为此时uniqeInstance已不为空,且synchronized方法只执行了一次,大大节省了资源。
优点:这种写法确保了线程安全还又节省了资源。
细品你终会有所收获!!!