单列中的四种实现方式
方式一:普通的懒汉式和饿汉式单例模式
三部曲:
(1)私有化构造方法
(2)私有化静态本类对象作为属性
(3)提供公有静态方法获取本类对象
//饿汉式单例模式
public class Boss{
//属性
private String name;
private int age;
//私有化构造方法
private Boss(String name, int age){
this.name = name;
this.age = age;
}
//私有静态本类对象作为属性
private static Boss boss = new Boss("马云",12);
//提供共有静态方法获取本类对象
public static Boss getBoss(){
return boss;
}
}
//懒汉式单例模式
public class Boss{
//属性
private String name;
private int age;
//私有化构造方法
private Boss(String name, int age){
this.name = name;
this.age = age;
}
//私有静态本类对象作为属性
private static Boss boss;
//提供共有静态方法获取本类对象
public static Boss getBoss(){
if(boss==null){
boss = new Boss("马云",12);
}
return boss;
}
}
饿汉式创建对象直接实例化,缺点是浪费内存,优点是没有线程安全问题;
懒汉式使用的时候才实例化,优点是节省内存,缺点是线程不安全。
方式二:静态内部类写法
在静态内部类中实例化私有静态常量对象再通过公有的静态方法拿到静态内部类中的对象。
由于静态内部类在使用时才加载,节省了内存空间。
public class SingleTon{
private SingleTon(){
}
static class Holder{
private static final SingleTon INSTACNE=new SingleTon();
}
public static SingleTon getInstance(){
return Holder.INSTACNE;
}
}
优点:节省空间,没有线程安全问题
缺点:反射破解问题,将在方式四中讲到
方式三:枚举写法
枚举方法简单易懂
public enum SingleTon {
INSTANCE;
public static SingleTon getInstance(){
return INSTANCE;
}
}
优点:线程安全,不能通过反射破解
缺点:枚举生命周期长,浪费内存空间
方式四:懒汉式写法的加强完善最终版
(1)构造方法加锁防止反射破解
(2)volatile关键字防止JVM指令重排序
(3)双重null判断提高效率:拿到instance后无需进行同步
public class SingleTon {
private SingleTon() {
//禁止反射破解
synchronized (SingleTon.class) {
if (instance != null) {
throw new RuntimeException("不能使用反射创建对象");
}
}
}
private static volatile SingleTon instance; //volatile:不稳定的,易挥发的
public static SingleTon getInstance() {
if (instance == null) { //double check.提高效率
synchronized (SingleTon.class) {
if (instance == null) { //判断为null
instance = new SingleTon();
}
}
}
return instance;
}
}
优点:线程安全,节省内存,防止反射破解。
今天的分享就这么多…
单例设计模式是面试中常常问到的内容,大家要牢牢掌握。