JAVA就业面试题
4.1单例模式

​ 单例,就是整个程序有且仅有一个实例。该类负责创建自己的对象,同时确保只有一个对象被创建。

特点

持有自己类型的属性
类构造器私有
对外提供获取实例的静态方法

4.1.1 懒汉式

/**

  • Created by 张晨光 on 2020/6/12 11:07
  • 懒汉式
    */
    public class Banzhang {
    //1.自己类的静态属性
    private static Banzhang bz;
    //2.私有的构造方法
    private Banzhang(){}
    //3.提供对外获取实例的静态方法
    public static Banzhang getInstance(){
    if(bz==null)
    bz= new Banzhang();
    return bz;
    }
    }

问题,线程不安全,延迟初始化,问题在 12行;
4.1.2 饿汉式

线程安全,比较常用,但容易产生垃圾,因为一开始就初始化

/**

  • Created by 张晨光 on 2020/6/12 11:12
  • 饿汉式
    */
    public class SingleTon {
    //1.静态自己本身属性;
    private static SingleTon singleTon=new SingleTon();
    //2.私有构造方法;
    private SingleTon(){}
    //3.提供静态的方法实例;
    public static SingleTon getInstance(){
    return singleTon;
    }
    }

饿汉式:立即加载;

懒汉式:延迟加载;–》节省资源
4.1.3 双重锁模式

双重检查模式,进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。由于singleton=new Singleton()对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题。

/**

  • Created by 张晨光 on 2020/6/12 11:22
  • 双重锁模式
    */
    public class Monitor {
    private volatile static Monitor monitor;
    private Monitor(){}
    private static Monitor getInstance(){
    if(monitor==null){
    synchronized (Monitor.class){
    if(monitor==null)
    monitor=new Monitor();
    }
    }
    return monitor;
    }
    }

4.1.4 静态内部类

​ 只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。目前此方式是所有单例模式中最推荐的模式,但具体还是根据项目选择。

/**

  • Created by 张晨光 on 2020/6/12 11:29
  • 静态内部类
    */
    public class JtSingleTon {
    //private static JtSingleTon jtSingleTon;
    private JtSingleTon(){}
    private static JtSingleTon getInstance(){
    return Inner.jtSingleTon;
    }
    private static class Inner{
    private static final JtSingleTon jtSingleTon=new JtSingleTon();
    }
    }

4.1.5 枚举实现

首先是再了解一下枚举

/**

  • Created by 张晨光 on 2020/6/12 15:36
  • 枚举测试;先来理解枚举的原理;
    */
    public enum EnumSingleTon {
    INSTANCE; //关键字;
    private EnumSingleTon(){
    System.out.println("初始化...");
    }
    public static EnumSingleTon getInstance(){
    return INSTANCE;
    }
    }

使用枚举的这种,只初始化一次的特征,来实现单例。

package single;

/**

  • Created by 张晨光 on 2020/6/12 15:42
  • User类,使用枚举实现;
    */
    public class User {
    //1.私有的构造方法;
    private User(){}
    //2.利用枚举类来获取实例;在这里放一个枚举SingleTon
    static enum SingleTon{
    //有一个枚举对象,天生为单例;
    INSTANCE;
    private User user;
    //私有的枚举构造方法;只被初始化一次;
    private SingleTon(){
    user=new User();
    }
    //由枚举提供一个获取User类的实例方法
    public User getInstance(){
    return user;
    }
    }
    //3.通过枚举来获取单例;
    public static User getInstance(){
    return SingleTon.INSTANCE.getInstance();
    }
    }

//调用测试方法,来测试User类是否单例的实现;br/>@Test
public void testEnumUser(){
User est1=User.getInstance();
User est2=User.getInstance();
System.out.println(est1);
System.out.println(est2);
}

总结:

​ 1.理解:单例的概念

​ 2.了解:懒汉式和饿汉式;建议会写静态内部类的实现;

用枚举类来获取实例;在这里放一个枚举SingleTon
static enum SingleTon{
//有一个枚举对象,天生为单例;
INSTANCE;
private User user;
//私有的枚举构造方法;只被初始化一次;
private SingleTon(){
user=new User();
}
//由枚举提供一个获取User类的实例方法
public User getInstance(){
return user;
}
}
//3.通过枚举来获取单例;
public static User getInstance(){
return SingleTon.INSTANCE.getInstance();
}
}


//调用测试方法,来测试User类是否单例的实现;
@Test
public void testEnumUser(){
    User est1=User.getInstance();
    User est2=User.getInstance();
    System.out.println(est1);
    System.out.println(est2);
}

    9
    10

总结:

​ 1.理解:单例的概念

​ 2.了解:懒汉式和饿汉式;建议会写静态内部类的实现;

​ 3.其他的知道即可,根据自己的程度,看看就行了。
————————————————