单例模式
1.饿汉式
1.1描述
单例模式的饿汉类型,是无论我们需不需要实例,我们都自主的去创建实例。在类生成的同时就实现实例的创建,主旨思想为“我都要”。
1.2优缺点
优点:线程安全,创建的实例属于类的成员,且无法被修改
缺点:无论创建的实例是否使用均会创建实例来占用内存空间
1.2代码实现
public class User {
/**
* 主动在类生成时创建一个私有的静态的不可变的实例对象
*/
public static final User user=new User();
/**
* 将唯一的构造方法进行私有化,使得从外部无法直接new新的实例
*/
private User(){}
/**
* 创建一个静态的方法获取我们创建的单例对象
* @return
*/
public static User getUser(){
return user;
}
}
2.懒汉式
2.1描述
懒汉式实在我们需要时才去创建实例,第一次调用获得实例的方法时,会在方法中判断成员实例为空然后创建实例。
2.2优缺点
优点:内存占用小,延迟加载,仅在需要时创建实例
缺点:加锁,使得多线程情况下需要等待,导致效率第下。
2.3代码实现
public class User {
/**
* 创建一个空对象最为单例的基础容器
*/
public static User user=null;
/**
* 将唯一的构造方法进行私有化,使得从外部无法直接new新的实例
*/
private User(){}
/**
* 创建一个静态的方法获取我们创建的单例对象
* 调用该方法时若成员单例为空则创建实例对象
* 加锁实现线程安全
* @return
*/
public static synchronized User getUser(){
if(user==null){
user=new User();
}
return user;
}
}
2.4效率优化
通过锁代码块与双重检查来将锁的范围减小,只有在第一次多线程并发访问获取实例方法时需要进行锁等待
再用volatile关键字修饰成员实例变量,防止指令重排序
(JMM线程三大特性:原子性,可见性,有序性,volatile针对可见性和有序性有解决方案,懒汉式单例模式主要使用其有序性特点)
代码实现
public class User {
/**
* 创建一个空对象最为单例的基础容器
* 使用volatile防止指令重排序
*/
public static volatile User user = null;
/**
* 将唯一的构造方法进行私有化,使得从外部无法直接new新的实例
*/
private User() {
}
/**
* 创建一个静态的方法获取我们创建的单例对象
* 调用该方法时若成员单例为空则创建实例对象
* 加锁实现线程安全
* @return
*/
public static User getUser() {
//此判断只为提高效率
if (user != null) {
//锁代码块仅对创建实例进行锁机制
synchronized (User.class) {
//防止并发访问被锁监听后创建多个实例
if (user != null) {
user = new User();
}
}
}
return user;
}
}
3.最优单例模式
3.1描述
通过静态内部类来实现单例,静态内部类不使用则不加载,所以有延迟加载特性;
静态内部类为静态类,其中有一个静态成员方法,使用static修饰符后的类,方法,属性无论多少线程访问均只加载一次
3.2代码实现
public class Item {
private Item(){}
public static Item getItem(){
return InnerItem.item;
}
/**
* 使用静态内部类实现单例
*/
static class InnerItem{
private static Item item=new Item();
}
}