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.其他的知道即可,根据自己的程度,看看就行了。
————————————————
来源:oschina
链接:https://my.oschina.net/u/4375351/blog/4310795