单例模式: 在应用整个生命周期内只能存在一个实例。
单例模式与静态类的区别:(静态类:类中都是静态方法和静态属性,构造器被private修饰,不能实例化。(Math类就是一个静态类))
1 单例模式全局就一个对象,静态类不用创建对象,通过类直接调用静态方法;
2 单例模式灵活性更高,方法可以被重写;静态类是静态方法不能重写;
3 如果是重对象,单例模式可以懒加载,静态类不可以。
单例-饿汉模式:立即加载,一般情况下再调用getInstancef方法之前就已经产生了实例(适合占用资源少,在初始化的时候就会被用到的类。)
class SingletonHungary{
private static SingletonHungary singletonHungary = new SingletonHungary();
//构造器私有,禁止通过new进行实例化
private SingletonHungary(){
}
public static SingletonHungary getInstance(){
return singletonHungary;
}
}
单例-懒汉模式:延迟加载,也叫懒加载。程序需要用到的时候再创建实例(多线程并发的环境下可能出现资源同步问题,线程不安全的),
class SingletonHungary{
private static SingletonHungary singletonHungary;
//构造器私有,禁止通过new进行实例化
private SingletonHungary(){
}
public static SingletonHungary getInstance(){
if (null == singletonLazy) {
singletonHungary = new SingletonHungary();
}
return singletonHungary;
}
}
懒汉模式-线程安全1: synchronized 同步的 修饰方法:下个线程想要取得对象,就必须要等上一个线程释放,才可以继续执行。
// 通过设置同步方法,效率太低,整个方法被加锁
一 (效率太低)
class SingletonHungary{
private static SingletonHungary singletonHungary;
private SingletonHungary(){
}
public static synchronized SingletonHungary getInstance(){
if (null == singletonLazy) {
singletonHungary = new SingletonHungary();
}
return singletonHungary;
}
}
二 (线程不安全)
class SingletonHungary{
private static SingletonHungary singletonHungary;
private SingletonHungary(){
}
public static synchronized SingletonHungary getInstance(){
if (null == singletonLazy) {
synchronized (SingletonLazy.class) {
singletonHungary = new SingletonHungary();
}
}
return singletonHungary;
}
}
懒汉模式-线程安全:实现单例模式的最优解。DCL双重检查锁机制,解决了单例模式的懒汉线程不安全问题和效率问题
class SingletonHungary{
private static volatile SingletonHungary singletonHungary;
private SingletonHungary(){
}
public static synchronized SingletonHungary getInstance(){
synchronized (SingletonLazy.class) {
if (null == singletonLazy) {
singletonHungary = new SingletonHungary();
}
}
return singletonHungary;
}
}
(volatile关键字的一个作用是禁止指令重排,把instance声明为volatile之后,对它的写操作就会有一个内存屏障(什么是内存屏障?),这样,在它的赋值完成之前,就不用会调用读操作。)
静态内部类:
class SingletonHungary{
private static class SingletonHolder {
private static final SingletonHungary INSTANCE = new SingletonHungary();
}
private SingletonHungary(){
}
public static final SingletonHungary getInstance(){
return SingletonHolder.INSTANCE;
}
}
说明:
对于内部类SingletonHolder,它是一个饿汉式的单例实现,在SingletonHolder初始化的时候会由ClassLoader来保证同步,使INSTANCE是一个真·单例。
同时,由于SingletonHolder是一个内部类,只在外部类的Singleton的getInstance()中被使用,所以它被加载的时机也就是在getInstance()方法第一次被调用的时候。
它利用了ClassLoader来保证了同步,同时又能让开发者控制类加载的时机。从内部看是一个饿汉式的单例,但是从外部看来,又的确是懒汉式的实现。
单元素的枚举类型:
public enum SingleInstance {
INSTANCE;
public void fun1() {
// do something
}
}
// 使用
SingleInstance.INSTANCE.fun1();
说明:
创建枚举实例的过程是线程安全的,所以这种写法也没有同步的问题。
单元素的枚举类型已经成为实现Singleton的最佳方法。
但是它仍然不是完美的——比如,在需要继承的场景,它就不适用了。
java 单例模式
最新推荐文章于 2023-05-09 10:56:14 发布