单例模式
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
主要有两种单例模式的写法
懒汉式
懒汉式定义:第一次被引用的时候才会将自己实例化
懒汉式写法又分为线程安全的和线程不安全的写法。
线程不安全写法
/**
* @author 州牧
* @description 线程不安全
* @since 2022-03-26 16:03
*/
public class Singleton1 {
private static Singleton1 singleton;
private Singleton1(){}
public static Singleton1 getInstance(){
if(singleton == null){
/*当多个线程同时通过这个条件,就会有多个实例*/
singleton = new Singleton1();
}
return singleton;
}
}
class App{
public static void main(String[] args) {
Singleton1 singleton1 = Singleton1.getInstance();
Singleton1 singleton2 = Singleton1.getInstance();
System.out.println("匹配哈希值:"+(singleton1==singleton2));
}
}
线程安全写法,加锁
/**
* @author 州牧
* @description 线程安全
* @since 2022-03-26 16:24
*/
public class Singleton2 {
private static Singleton2 singleton;
private Singleton2(){}
//写法一 双重锁定
public static Singleton2 getInstance(){
if(singleton == null){
synchronized (Singleton2.class){
singleton = new Singleton2();
}
}
return singleton;
}
//写法二 同步
// public static synchronized Singleton2 getInstance(){
// if(singleton == null){
// singleton = new Singleton2();
// }
//
// return singleton;
// }
}
双重锁定写法性能上是高于同步写法的,双重锁定写法在单例被判断为空才会进入下面的锁代码块,而同步方法每次想要创建实例时,都要经过锁代码块。
此外,通过博客还了解到一种静态内部类的写法,这种写法不需要加锁,却也是懒汉式加载,是最佳写法
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
原文出处:https://blog.youkuaiyun.com/jason0539/article/details/23297037
饿汉式
饿汉式定义:类被加载的时候就会被实例化
饿汉式天生就是线程安全的,static关键字修饰单例,类被加载的时候就会加载这个单例
public class Singleton3 {
private static final Singleton3 singleton = new Singleton3() ;
private Singleton3(){}
public static Singleton3 getInstance(){
return singleton;
}
}
饿汉式是静态初始化的方式,必定提前占用系统资源,而懒汉式是引用的方式创建,未必会占用资源。