单例模式:创建型模式,保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
饿汉式:线程安全,调用效率高,不能延时加载
public class SingtonDemo {
//私有构造方法,这样外面就不能创建对象了
private SingtonDemo() {
}
// 被static修饰的变量,属于类本身(可以通过类名加 . 进行访问),不属于某一个对象
// 当该类的static变量被修改时,所有对象的static成员变量也会被修改
private static SingtonDemo singtonDemo = new SingtonDemo();
//提供一个获取该对象的方法,实现每次获取都是这一个对象
public static SingtonDemo getInstance() {
return singtonDemo;
}
}
class SingtonDemoTest {
public static void main(String[] args) {
SingtonDemo singtonDemo = SingtonDemo.getInstance();
SingtonDemo singtonDemo1 = SingtonDemo.getInstance();
System.out.println(singtonDemo == singtonDemo1); //true
}
}
懒汉式:线程安全,调用效率不高,能延时加载
饿汉式的缺点,如果在程序运行很长时间还没有用到初始就加载的对象,会导致资源的浪费,懒汉式来解决用的时候再加载
public class SingtonDemo {
//私有构造方法,这样外面就不能创建对象了
private SingtonDemo() {
}
private static SingtonDemo singtonDemo;
//提供一个获取该对象的方法,实现每次获取都是这一个对象,为防止多线程创建多个对象用synchronized
public static synchronized SingtonDemo getInstance() {
if(singtonDemo == null) {
singtonDemo = new SingtonDemo();
}
return singtonDemo;
}
}
class SingtonDemoTest {
public static void main(String[] args) {
SingtonDemo singtonDemo = SingtonDemo.getInstance();
SingtonDemo singtonDemo1 = SingtonDemo.getInstance();
System.out.println(singtonDemo == singtonDemo1); //true
}
}
双重检查锁(DCL懒汉式)
class SingtonDemo {
private SingtonDemo() {
}
private volatile static SingtonDemo singtonDemo;
public static SingtonDemo getInstance() {
if(singtonDemo == null) {
synchronized (SingtonDemo.class) {
if (singtonDemo == null) {
// 由于这个new操作非原子性
// 1、申请内存空间,2、初始化对象,3、将该对象放到内存空间中
// 正常执行顺序时123,如果发生了指令重排,可能执行顺序为132
// 这样一来,内存空间中就有了未初始化的对象
// 当线程A来new对象的时候执行了13,此时,线程B刚好走第一个if
// 这样一来,线程B就以为singtonDemo非空,而获得了一个未初始化的对象
// 解决方案,给SingtonDemo加volatile关键字,禁止指令重排。
singtonDemo = new SingtonDemo();
}
}
}
return singtonDemo;
}
}