单例模式
简介:一种简单的设计模式,可以保证全局只有一个对象被创建,无需手动创建对象,可通过类名.方法名直接调用(这里为get方法),细分为饿汉式、懒汉式、单重锁、双重锁。
作用:解决一个全局使用的类被频繁创建与频繁销毁的问题。
饿汉式:
类被加载时,同时创建对象。
优点:线程绝对安全
缺点:由于加载类的时候就会创建对象,所以不过是否使用,都会占用内存,造成内存浪费。
代码:
class A{
//构造方法私有化
private A() {
}
private static final A a = new A();
//创建对象的方法
public static A get(){
return a;
}
}
懒汉式:
调用特定方法时(这里为get方法),创建对象
优点:只有当使用时才会创建对象,不会造成内存浪费。
缺点:线程不安全,当有多个线程同时访问特定方法时(这里为get方法),可能会造成创建多个对象。
代码:
class A{
//构造方法私有化
private A() {
}
private static A a;
//创建对象的方法
public static A get(){
if(a==null){
a = new A();
}
return a;
}
}
单重锁:
在懒汉式的基础上,将特定方法(这里为get方法)加锁,使同一时间只能用一个线程访问。
优点:线程安全。
缺点:只有在初始化的时候才会有线程安全问题,当第一个对象被创建,线程安全问题就不存在了。但同步锁依然存在,会降低代码的执行效率。
代码:
class A{
//构造方法私有化
private A() {
}
private static A a;
//创建对象的方法
public static synchronized A get(){
if(a==null){
a = new A();
}
return a;
}
}
双重锁:
在单重锁的基础上,进行了判断,只用在初始化的时候才会用到锁。
优点:线程安全。
缺点:JVM在实例化对象的时候会进行优化和指令重排序操作,造成空指针问题。
代码:
class A{
//构造方法私有化
private A() {
}
private static A a;
//创建对象的方法
public static A get(){
if(a==null){
//抢锁
synchronized (A.class){
if (a==null){
a = new A();
}
}
}
return a;
}
}