阿里java面试官问:写一个你认为最好的单例模式?怒写了7个

几种单例模式的优劣势 下面看看几种常见的单例的设计方式: 第一种:非延迟加载单例类(饿汉式) publicclassSingleton{ privateSingleton(){} privatestaticfinalSingletoninstance=newSingleton(); publicstaticSingletongetInstance(){ returninstance; } } 饿汉式不存在线程安全问题,但是如果初始... 阅读详情

面试题:写一个你认为最好的单例模式

面试考察点

考察目的: 单例模式可以考察非常多的基础知识,因此对于这种问题,很多面试官都会问。 小伙伴要注意,在面试过程中,但凡能够从多个维度考察求职者能力的题目,一定不会被抛弃,特别是比较泛的问题,比如: ”请你说说对xxx的理解“之类。

考察范围: 工作1到5年经验,随着经验的提升,对于该问题的考察深度越深。

好友添加:huany6880 加入资深Java学习交流圈,并有系统整理了一套java初学/进阶者最佳的学习方法以及路 线图大纲,Java各核心知识点、架构主流技术资料/源码以及最新大厂面试题定期更新!

背景知识

单例模式,是一种软件设计模式,属于创建型模式的一种。

它的特性是:保证一个类只有唯一的一个实例,并提供一个全局的访问点。

基于这个特性可以知道,单例模式的好处是,可以避免对象的频繁创建对于内存的消耗,因为它限制了实例的创建,总的来说,它有以下好处:

  1. 控制资源的使用,通过线程同步来控制资源的并发访问;

  2. 控制实例产生的数量,达到节约资源的目的。

  3. 作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。

在实际应用中,单例模式使用最多的就是在Spring的IOC容器中,对于Bean的管理,默认都是单例。一个bean只会创建一个对象,存在内置map中,之后无论获取多少次该bean,都返回同一个对象。

下面来了解单例模式的设计。

单例模式设计

既然要保证一个类在运行期间只有一个实例,那必然不能使用new关键字来进行实例。

所以,第一步一定是私有化该类的构造方法,这样就防止了调用方自己创建该类的实例。

接着,由于外部无法实例化该对象,因此必须从内部实例化之后,提供一个全局的访问入口,来获取该类的全局唯一实例,因此我们可以在类的内部定义一个静态变量来引用唯一的实例,作为对外提供的实例访问对象。基于这些点,我们可以得到如下设计。

public class Singleton {
    // 静态字段引用唯一实例:
    private static final Singleton INSTANCE = new Singleton();

    // private构造方法保证外部无法实例化:
    private Singleton() {
    }
}

接着,还需要给外部一个访问该对象实例INSTANCE的方法,我们可以提供一个静态方法

public class Singleton {
    // 静态字段引用唯一实例:
    private static final Singleton INSTANCE = new Singleton();

    // 通过静态方法返回实例:
    public static Singleton getInstance() {
        return INSTANCE;
    }

    // private构造方法保证外部无法实例化:
    private Singleton() {
    }
}

这样就完成了单例模式的设计,总结来看,单例模式分三步骤。

  1. 使用private私有化构造方法,确保外部无法实例化;
  2. 通过private static变量持有唯一实例,保证全局唯一性;
  3. 通过public static方法返回此唯一实例,使外部调用方能获取到实例。

单例模式的其他实现#

既然单例模式只需要保证程序运行期间只会产生唯一的实例,那意味着单例模式还有更多的实现方法。

  • 懒汉式单例模式
  • 饿汉式单例模式
  • DCL双重检查式单例
  • 静态内部类
  • 枚举单例
  • 基于容器实现单例

懒汉式单例模式

懒汉式,表示不提前创建对象实例,而是在需要的时候再创建,代码如下。

public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    // synchronized方法,多线程情况下保证单例对象唯一
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

其中,对getInstance()方法,增加了synchronized同步关键字,目的是为了避免在多线程环境下同一时刻调用该方法导致出现多实例问题(线程的并行执行特性带来的线程安全性问题)。

优点: 只有在使用时才会实例化单例,一定程度上节约了内存资源。
缺点: 第一次加载时要立即实例化,反应稍慢。每次调用getInstance()方法都会进行同步,这样会消耗不必要的资源。这种模式一般不建议使用。

DCL双重检查式单例

DCL双重检查式单例模式,是基于饿汉式单例模式的性能优化版本。

/**
 * DCL实现单例模式
 */
public class Singleton {
    private static volatile Singleton instance = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        // 两层判空,第一层是为了避免不必要的同步
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {// 第二层是为了在null的情况下创建实例
                    instance = new Singleton();
                }
            }

        }
        return instance;
    }
}

从代码中可以看到,DCL模式做了两处改进:

  1. 在getInstance()方法中,把synchronized同步锁的加锁范围缩小了。

    缩小锁的范围能够带来性能上的提升,不妨思考一下,在原来的懒汉式模式中,把synchronized关键字加载方法级别上,意味着不管是多线程环境还是单线程环境,任何一个调用者需要获得这个对象实例时,都需要获得锁。但是加这个锁其实只有在第一次初始化该实例的时候起到保护作用。后续的访问,应该直接返回instance实例对象就行。所以把synchroinzed加在方法级别,在多线程环境中必然会带来性能上的开销。

    而DCL模式的改造,就是缩小了加锁的范围,只需要保护该实例对象instance在第一次初始化即可,后续的访问,都不需要去竞争同步锁。因此它的设计是:

    • 先判断instance实例是否为空,如果是,则增加synchronized类级别锁,保护instance对象的实例化过程,避免在多线程环境下出现多实例问题。
    • 接着再synchronized同步关键字范围内,再一次判断instance实例是否为空,同样也是为了避免临界点时,上一个线程刚初始化完成,下一个线程进入到同步代码块导致多实例问题。
  2. 在成员变量instance上修饰了volatile关键字,该关键字是为了保证可见性。

    之所以要加这个关键字,是为了避免在JVM中指令重排序带来的可见性问题,这个问题主要体现在instance=new Singleton()这段代码中。我们来看这段代码的字节码

     17: new           #3                  // class org/example/cl04/Singleton
     20: dup
     21: invokespecial #4                  // Method "<init>":()V
     24: putstatic     #2                  // Field instance:Lorg/example/cl04/Singleton;
     27: aload_0
     28: monitorexit
     29: goto          37
     32: astore_1
     33: aload_0
    
    

    关注以下几个指令

    • new #3 : 这行指令是说在堆上的某个地址处开辟了一块空间作为Singleton对象

    • invokespecial #4 :这行指令是说将对象里的成员变量进行赋值操作

    • astore_1 :这行指令是说将栈里的Singleton instance与堆上的对象建立起引用关联

    而invokespecial #4指令,和astore_1指令,是允许重排序的(关于重排序问题,就不再本篇文章中说明,后续的面试题中会分析到),就是说执行顺序有可能astore_1先执行, invokespecial #1后执行。

    重排序对于两个没有依赖关系的指令操作,CPU和内存以及JVM,为了优化程序执行性能,会对执行指令进行重排序。也就是说两个指令的执行顺序不一定会按照程序编写顺序来执行。

    因为在堆上建立对象开辟地址以后,地址就已经定了,而“将栈里的Singleton instance与堆上的对象建立起引用关联” 和 “将对象里的成员变量进行赋值操作” 是没什么逻辑关系的。

    所以cpu可以进行乱序执行,只要程序最终的结果是一致的就可以。

    这种情况,在单线程下没有问题,但是多线程下,就会出现错误。

    试想一下,DCL下,线程A在将对象new出来的时,刚执行完new #4指令,紧接着没有执行invokespecial #4指令,而是执行了astore_1,也就是说发生了指令重排序。

    此时线程B进入getInstance(),发现instance并不为空(因为已经有了引用指向了对象,只不过还没来得及给对象里的成员变量赋值),然后线程B便直接return了一个“半初始化”对象(对象还没彻底创建完)。

    所以DCL里,需要给instance加上volatile关键字,因为volatile在JVM层有一个特性叫内存屏障,可以防止指令重排序,从而保证了程序的正确性。

关于DCL模式的优缺点:

优点:资源利用率高,既能够在需要的时候才初始化实例,又能保证线程安全,同时调用getInstance()方法不进行同步锁,效率高。
缺点:第一次加载时稍慢,由于Java内存模型的原因偶尔会失败。在高并发环境下也有一定的缺陷,虽然发生概率很小。

DCL模式是使用最多的单例模式实现方式,除非代码在并发场景比较复杂,否则,这种方式基本都能满足需求。

饿汉式单例模式

在类加载的时候不创建单例实例。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。

/**
 * 饿汉式实现单例模式
 */
public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

由于static关键字修饰的属性,表示这个成员属于类本身,不属于实例,运行时,Java 虚拟机只为静态变量分配一次内存,在类加载的过程中完成静态变量的内存分配。

所以在类加载的时候就创建好对象实例,后续在访问时直接获取该实例即可。

而该模式的优缺点也非常明显。

优点:线程安全,不需要考虑并发安全性。

缺点:浪费内存空间,不管该对象是否被使用到,都会在启动是提前分配内存空间。

静态内部类

静态内部类,是基于饿汉式模式下的优化。

第一次加载Singleton类时不会初始化instance,只有在第一次调用getInstance()方法时,虚拟机会加载SingletonHolder类,初始化instance。instance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。

/**
 * 静态内部类实现单例模式
 */
public class Singleton {
  private Singleton() {
  }

  public static Singleton getInstance() {
    return SingletonHolder.instance;
  }

  /**
     * 静态内部类
     */
  private static class SingletonHolder {
    private static Singleton instance = new Singleton();
  }
}

这种方式既保证线程安全,单例对象的唯一,也延迟了单例的初始化,推荐使用这种方式来实现单例模式。

静态内部类不会因为外部内的加载而加载,同时静态内部类的加载不需要依附外部类,在使用时才加载,不过在加载静态内部类的过程中也会加载外部类

知识点:如果用static来修饰一个内部类,那么就是静态内部类。这个内部类属于外部类本身,但是不属于外部类的任何对象。因此使用static修饰的内部类称为静态内部类。静态内部类有如下规则:

  • 静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
  • 外部类可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象访问其实例成员。

静态内部类单例优点:

  • 对象的创建是线程安全的。
  • 支持延时加载。
  • 获取对象时不需要加锁。

这是一种比较常用的模式之一。

基于枚举实现单例

用枚举来实现单例,是最简单的方式。这种实现方式通过Java枚举类型本身的特性,保证了实例创建的线程安全性和实例的唯一性。

public enum SingletonEnum {

    INSTANCE;

    public void execute(){
        System.out.println("begin execute");
    }

    public static void main(String[] args) {
        SingletonEnum.INSTANCE.execute();
    }
}

基于枚举实现单例会发现它并不需要前面描述的几个操作

  1. 构造方法私有化
  2. 实例化的变量引用私有化
  3. 获取实例的方法共有

这类的方式实现枚举其实并不保险,因为私有化构造并不能抵御反射攻击.

这种方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊。

基于容器实现单例

下面的代码演示了基于容器的方式来管理单例。

import java.util.HashMap;
import java.util.Map;
/**
 * 容器类实现单例模式
 */
public class SingletonManager {
    private static Map<String, Object> objMap = new HashMap<String, Object>();

    public static void regsiterService(String key, Object instance) {
        if (!objMap.containsKey(key)) {
            objMap.put(key, instance);
        }
    }

    public static Object getService(String key) {
        return objMap.get(key);
    }
}

SingletonManager可以管理多个单例类型,在程序的初始化时,将多个单例类型注入到一个统一管理的类中,使用时根据key获取对象对应类型的对象。这种方式可以通过统一的接口获取操作,隐藏了具体实现,降低了耦合度。

关于单例模式的破坏

前面在分析枚举类实现单例模式时,有提到一个问题,就是私有化构造,会被反射破坏,导致出现多实例问题。

public class Singleton {

    private static volatile Singleton instance = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        // 两层判空,第一层是为了避免不必要的同步
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {// 第二层是为了在null的情况下创建实例
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) throws Exception{
        Singleton instance=Singleton.getInstance();
        Constructor<Singleton> constructor=Singleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Singleton refInstance=constructor.newInstance();
        System.out.println(instance);
        System.out.println(refInstance);
        System.out.println(instance==refInstance);

    }
}

运行结果如下

org.example.cl04.Singleton@29453f44
org.example.cl04.Singleton@5cad8086
false

由于反射可以破坏private特性,所以凡是通过private私有化构造实现的单例模式,都能够被反射破坏从而出现多实例问题。

可能有人会问,我们没事干嘛要去破坏单例呢? 直接基于这个入口访问就不会有问题啊?

理论上来说是这样,但是,假设遇到下面这种情况呢?

下面的代码演示的是通过对象流实现Singleton的序列化和反序列化。

public class Singleton implements Serializable {

    private static volatile Singleton instance = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        // 两层判空,第一层是为了避免不必要的同步
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {// 第二层是为了在null的情况下创建实例
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) throws Exception {
        Singleton instance=Singleton.getInstance();
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(baos);
        oos.writeObject(instance);
        ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bais);
        Singleton ri=(Singleton) ois.readObject();
        System.out.println(instance);
        System.out.println(ri);
        System.out.println(instance==ri);
    }
}

运行结果如下

org.example.cl04.Singleton@36baf30c
org.example.cl04.Singleton@66a29884
false

可以看到,序列化的方式,也会破坏单例模式。

枚举类单例的破坏测试

可能有人会问,枚举难道就不能破坏吗?

我们可以试试看,代码如下。

public enum SingletonEnum {

    INSTANCE;

    public void execute(){
        System.out.println("begin execute");
    }

    public static void main(String[] args) throws Exception{
        SingletonEnum instance=SingletonEnum.INSTANCE;
        Constructor<SingletonEnum> constructor=SingletonEnum.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        SingletonEnum refInstance=constructor.newInstance();
        System.out.println(instance);
        System.out.println(refInstance);
        System.out.println(instance==refInstance);
    }
}

运行结果如下

Exception in thread "main" java.lang.NoSuchMethodException: org.example.cl04.SingletonEnum.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082)
	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
	at org.example.cl04.SingletonEnum.main(SingletonEnum.java:15)

从错误来看,似乎是没有一个空的构造函数?这里并没有证明 反射无法破坏单例。

下面是Enum这类的源码,所有枚举类都继承了Enum这个抽象类。

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    /**
     * The name of this enum constant, as declared in the enum declaration.
     * Most programmers should use the {@link #toString} method rather than
     * accessing this field.
     */
    private final String name;

    /**
     * Returns the name of this enum constant, exactly as declared in its
     * enum declaration.
     *
     * <b>Most programmers should use the {@link #toString} method in
     * preference to this one, as the toString method may return
     * a more user-friendly name.</b>  This method is designed primarily for
     * use in specialized situations where correctness depends on getting the
     * exact name, which will not vary from release to release.
     *
     * @return the name of this enum constant
     */
    public final String name() {
        return name;
    }

    /**
     * The ordinal of this enumeration constant (its position
     * in the enum declaration, where the initial constant is assigned
     * an ordinal of zero).
     *
     * Most programmers will have no use for this field.  It is designed
     * for use by sophisticated enum-based data structures, such as
     * {@link java.util.EnumSet} and {@link java.util.EnumMap}.
     */
    private final int ordinal;

    /**
     * Returns the ordinal of this enumeration constant (its position
     * in its enum declaration, where the initial constant is assigned
     * an ordinal of zero).
     *
     * Most programmers will have no use for this method.  It is
     * designed for use by sophisticated enum-based data structures, such
     * as {@link java.util.EnumSet} and {@link java.util.EnumMap}.
     *
     * @return the ordinal of this enumeration constant
     */
    public final int ordinal() {
        return ordinal;
    }

    /**
     * Sole constructor.  Programmers cannot invoke this constructor.
     * It is for use by code emitted by the compiler in response to
     * enum type declarations.
     *
     * @param name - The name of this enum constant, which is the identifier
     *               used to declare it.
     * @param ordinal - The ordinal of this enumeration constant (its position
     *         in the enum declaration, where the initial constant is assigned
     *         an ordinal of zero).
     */
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
}

该类有一个唯一的构造方法,接受两个参数分别是:name和ordinal

那我们尝试通过这个构造方法来创建一下实例,演示代码如下。

public enum SingletonEnum {

    INSTANCE;

    public void execute(){
        System.out.println("begin execute");
    }

    public static void main(String[] args) throws Exception{
        SingletonEnum instance=SingletonEnum.INSTANCE;
        Constructor<SingletonEnum> constructor=SingletonEnum.class.getDeclaredConstructor(String.class,int.class);
        constructor.setAccessible(true);
        SingletonEnum refInstance=constructor.newInstance("refinstance",2);
        System.out.println(instance);
        System.out.println(refInstance);
        System.out.println(instance==refInstance);
    }
}

运行上述代码,执行结果如下

Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
	at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
	at org.example.cl04.SingletonEnum.main(SingletonEnum.java:17)

从错误信息来看,我们成功获取到了Constructor这个构造器,但是在newInstance时报错。

定位到出错的源码位置。

if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        ConstructorAccessor ca = constructorAccessor;   // read volatile

从这段代码:(clazz.getModifiers() & Modifier.ENUM) != 0说明:反射在通过newInstance创建对象时,会检查该类是否ENUM修饰,如果是则抛出异常,反射失败,因此枚举类型对反射是绝对安全的。

既然反射无法破坏?那序列化呢?我们再来试试

public enum SingletonEnum {

    INSTANCE;

    public void execute(){
        System.out.println("begin execute");
    }
    public static void main(String[] args) throws Exception{
        SingletonEnum instance=SingletonEnum.INSTANCE;
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(baos);
        oos.writeObject(instance);
        ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bais);
        SingletonEnum ri=(SingletonEnum) ois.readObject();
        System.out.println(instance);
        System.out.println(ri);
        System.out.println(instance==ri);
    }
}

运行结果如下.

INSTANCE
INSTANCE
true

因此,我们可以得出一个结论,枚举类型是所有单例模式中唯一能够避免反射破坏导致多实例问题的设计模式。

综上,可以得出结论:枚举是实现单例模式的最佳实践。毕竟使用它全都是优点:

  1. 反射安全

  2. 序列化/反序列化安全

  3. 写法简单

问题解答

面试题:写一个你认为最好的单例模式

对于这个问题,相比大家都有答案了,枚举方式实现单例才是最好的。

当然,回答的时候要从全方面角度去讲解。

  1. 单例模式的概念
  2. 有哪些方式实现单例
  3. 每种单例模式的优缺点
  4. 最好的单例模式,以及为什么你觉得它是最好的?

问题总结

单例模式看起来简单,但是学到极致,也还是有很多知识点的。

比如涉及到线程安全问题、静态方法和静态从成员变量的特征、枚举、反射等。

多想再回到从前,大家都只用jsp/servlet,没有这么多乱七八糟的知识,我们只想做个简单的程序员。好友添加:huany6880 加入资深Java学习交流圈,并有系统整理了一套java初学/进阶者最佳的学习方法以及路 线图大纲,Java各核心知识点、架构主流技术资料/源码以及最新大厂面试题定期更新!

小白学电路之cadance搭建buffer电路 Buffer(缓冲器)是一种放大器或驱动电路,主要用于隔离输入和输出,以防止负载对前级电路造成干扰或影响。本文作者在电路方面是小白水平,目前正在学习,有不足之处欢迎指正。3.创建新的cellview,对此buffer进行仿真验证。2.创建buffer的symbol。电路中的V2的详细参数。 阅读详情

相关推荐

Arduino智能小灯DIY:人体感应+光线感应+蓝牙控制全攻略(附完整代码)

本文提供了一份完整的Arduino智能小灯DIY制作指南。项目融合了人体感应、光线感应与蓝牙控制三大功能,通过详细的硬件清单、电路连接图、核心逻辑讲解及附带的完整代码,手把手教你打造一个能自动感知环境与人、并支持手机远程控制的智能照明装置,是入门智能家居和物联网开发的绝佳实践。

java5的博客 1094

java 中的单例模式,三种最佳实例

java 中单例模式的五种实现方式,两种简单实现,三种最佳实践

yk950309的博客 1271

【在英伟达nvidia的jetson-orin-nx上使用调试can基础收发-硬件连接-开机自启动can-初步调试】

近期开始学习英伟达的工控板,作为新手还是有很多不同懂得地方,但是一部分它用的linux系统,有点像玩树莓派,通过自己一段时间学习can调试,终于可以简单通信了。开始的时候,自己也是什么都不是很懂,从新手一点点摸索过来,现在使用工控机,简单can通信也已经没有问题了,算是有些进步吧。每一步走的都很艰辛,需要反复验证,才能准去无误,开始以为发送没有问题就没事了,没想到发送可以却接受不行,每一步都要反复确认啊,这个问题会持续关注下吧。

qq_22146161的博客 6120

单例模式的5种实现方式,最后一种最推荐

单例模式有多种实现方式,选择哪种方式取决于你的具体需求。如果你希望在程序启动时就创建实例,可以选择饿汉式;如果你希望在需要时才创建实例,可以选择懒汉式、静态内部类或枚举。在多线程环境下,需要注意线程安全问题。希望本文能帮助你更好地理解和使用单例模式。

QiuMing 4034

利用python-docx提取word的高亮部分

利用python-docx提取word的高亮部分 没有找到分享的文档,于是就自己研究了一下。 可以通过python里的python-docx去提取word内的高亮文本。 file=docx.Document(filepath) for para in file.paragraphs: for i in para.runs: #i.font.highlight_color设置了高亮颜色 if i.font.highlight_color is not None:

double_0221的博客 1809

从SolidWorks到Simulink:手把手教你用URDF文件搭建六轴机械臂仿真模型(含STL文件配置避坑)

本文详细介绍了从SolidWorks到Simulink的六轴机械臂URDF仿真全流程,包括URDF文件导出、Simscape模型生成与调试、动力学参数获取与验证等关键步骤。重点解决了STL文件配置、关节接口设置等工程化难题,帮助开发者高效构建可控制的数字孪生体。通过实战案例和优化技巧,提升机械臂仿真效率与准确性。

weixin_26812607的博客 265

总结单例模式的几种实现方式及优缺点

一、单例模式的定义 确保这个类在内存中只会存在一个对象,而且自行实例化并向整个应用系统提供这个实例。 二、单例模式的应用场景 一般创建一个对象需要消耗过多的资源,如:访问I0和数据库等资源或者有很多个地方都用到了这个实例。 三、单例模式的几种基本写法: 饿汉式 public class Singleton { private static final Singleton INSTANCE=new Singleton(); private Singleton(){} ...

骏马逸动,心随你动的博客 1482

YOLOv11 改进 - SPPF模块 | 发论文神器!LSKA注意力改进SPPF,增强多尺度特征提取能力,高效涨点!!!

本文介绍了Large Separable Kernel Attention (LSKA)模块及其在YOLOv11中的结合应用。LSKA旨在解决Visual Attention Networks (VAN)使用大内核卷积时的计算效率问题,通过将2D深度卷积层的卷积核分解为级联的水平和垂直1-D卷积核,降低了计算复杂度和内存占用,且使VAN更关注物体形状。我们将集成LSKA的SPPF_LSKA模块引入YOLOv11,大量实验表明,改进后的模型在对象识别、检测、分割和稳健性测试上表现出色。

魔改工程师的博客 1279

Java设计模式——单例模式

单例模式应该是日常开发中用得最多的设计模式了,它的思想就是保证在应用中一个类的实例只能有一个。 什么情形下需要用到单例模式? 在程序中我们经常会遇到有类似配置文件的需求,一般在整个应用中配置信息应该都是需要共享同一份的,这时可以利用单例模式,保证在程序中用到此配置类的实例时,都是同一个实例,保证程序运行的正确。 类似于这种情形还有很多,比如数据库,线程池等。针对这种共享的情形有人可能就会有疑问,那...

HelloTu的博客 272

beegfs源码分析

BeeGFS的客户端是由一个内核模块和两个系统服务组成的,这里咱们主要分析内核模块。由于BeeGFS的目录树解析,是在父目录DEntry里找子目录或文件DEntry,逐级迭代完成的,所以在Mount文件系统时,须要从管理节点获取根元数据节点的ID,而后再向根元数据节点查询根目录的DEntry的信息,为后续的目录解析打下基础。获取类似/data/beeond/data/dentries/38/51/root/#fSiDs#/文件fileId的父路径。1.1 FileID的生成。Session网络消息。

wfzy的博客 1913

电机驱动器MP6540H应用设计

/ ... 其他初始化函数(SystemClock_Config, MX_GPIO_Init, MX_TIM1_Init, MX_TIM2_Init)需要你根据STM32CubeMX生成或手动编写。// 假设霍尔传感器引脚是 GPIO_PIN_8, GPIO_PIN_9, GPIO_PIN_10。// 低侧U相GPIO引脚。

zhusl6688的博客 660

字节面试官问:写一个你认为最好的单例模式?于是我写了7个

在程序的初始化时,将多个单例类型注入到一个统一管理的类中,使用时根据key获取对象对应类型的对象。关键字修饰的属性,表示这个成员属于类本身,不属于实例,运行时,Java 虚拟机只为静态变量分配一次内存,在类加载的过程中完成静态变量的内存分配。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。前面在分析枚举类实现单例模式时,有提到一个问题,就是私有化构造,会被反射破坏,导致出现多实例问题。这种方式既保证线程安全,单例对象的唯一,也延迟了单例的初始化,

2401_84437170的博客 937

【反蒸馏实战 00】AI抢不走的工作:一份针对30个“高危”职位的“反取代”实战手册(反蒸馏计划启动)

AI时代职场生存指南:30个技术岗位的“反蒸馏”实战策略 随着AI技术快速发展,职场正面临前所未有的结构性重构。本系列专栏聚焦30个技术岗位,深入分析AI对各职位的影响路径,并提供系统性的"反蒸馏"策略。通过5层分析框架(AI冲击现状、核心价值解构、AI天花板、能力升级路径、人机协作模式),帮助从业者识别可替代任务与核心价值,建立不可替代的专业优势。内容涵盖IT开发、数据分析、产品管理等技术领域,为职场人提供从“被AI替代”到“与AI协同”的转型路线图,守护职业价值。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1648

如果你是一个 Java 面试官,你会问哪些问题?

这份笔记主要涵盖了 Java 基础、JVM、多线程&并发、Spring、MyBatis、SpringBoot、MySQL、SpringCloud、Dubbo、Nginx、MQ、数据结构与算法、Linux、Zookeeper 等内容。,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。上个月,我曾推荐过一个课程,它不仅能帮你解决技术学习的问题,**还能直接内推进大厂,**这门课是拉勾的**《Java工程师高薪训练营》****,**

2401_84048554的博客 659

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

2024年最全阿里面试官:简历上最好不要写Glide,不是问源码那么简单,2024年最新阿里p7面试经验

本文通过Glide开题,分析一个图片加载框架必要的需求,以及各个需求涉及到哪些技术和原理。异步加载:最少两个线程池切换到主线程:Handler缓存:LruCache、DiskLruCache,涉及到LinkHashMap原理防止OOM:软引用、LruCache、图片压缩没展开讲、Bitmap像素存储位置源码分析、Fresco部分源码分析内存泄露:注意ImageView的正确引用,生命周期管理列表滑动加载的问题:加载错乱用tag、队满任务存在则不添加。

2401_84557402的博客 860

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

阿里面试官:简历上最好不要写Glide,不是问源码那么简单(1)

有任何问题,欢迎广大网友一起来交流,分享高阶Android学习视频资料和面试资料包~偷偷说一句:群里高手如云,欢迎大家加群和大佬们一起交流讨论啊!《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!有任何问题,欢迎广大网友一起来交流,分享高阶Android学习视频资料和面试资料包~偷偷说一句:群里高手如云,欢迎大家加群和大佬们一起交流讨论啊![外链图片转存中…(img-uWb6yzwI-1715424599686)]

2401_84003733的博客 1000

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

分享:我在阿里做了10年技术面试官,这7个些建议能让你受益终身

我可能是在同龄人中做面试官经验比较丰富的,在某乎实习的时候就参与了Java的技术面试。后来在阿里以及另一家公司也面试过不少候选人,校招、社招、外包都有面试过。这里以一个面试官的角度来给大家谈谈在面试的时候怎么能给面试官留下更好的印象,更容易拿到大厂的Offer。为了不造成任何面试题泄露,这里我不会涉及到任何具体的面试题。 一、社招和校招的面试重点 社招其实和校招的面试重点有一些...

qq_39662660的博客 1693

阿里后端面试官的连环炮,看看你能撑到哪一步?

本内容来源于 16 年毕业的学长,先在 58,后阿里,如今准备跳槽了,以下内容为他的最近面试经历,我最近从大厂离职之后在合肥呆了个把月,之前已经准备了半个多月,从7月底开始投简历面试,目前是java高级职位,到现在为止已经面了24+公司了,手上也有一些意向offer。现在把跟面试官对垒的面试问题总体记录一下。

知识分享官 1249

做了两年P7面试官,谈谈我认为的阿里人才画像,你配吗?

经常会有读者问我以下类似的问题:达到什么水平才能进阿里?阿里的 P6 有哪些要求?我想进阿里,我要准备什么?到底什么样才算是高级开发? 图片来自 Pexels 刚好现在自己在阿里待了 5 年了,前 4 年里经历了两次晋升,从 P5 到 P7,算是大概了解了一些阿里对于人才的要求。 在阿里的这 5 年里,经历了太多太多,我也从一个刚刚毕业的懵懂少年,成长成一个独当一面的技术专家了。也回过头思考了很多很多。 所以,今天斗胆来谈一谈我认为的阿里的人才观,试着回答一下这几个问题。本文所有内容都是我.

互联网架构小马的博客 3263

如果你是一个 Java 面试官,你会问哪些问题?,2024年最新大厂的面试

这份笔记主要涵盖了 Java 基础、JVM、多线程&并发、Spring、MyBatis、SpringBoot、MySQL、SpringCloud、Dubbo、Nginx、MQ、数据结构与算法、Linux、Zookeeper 等内容。课程的学习路线,从**源码剖析、框架优化和定制、分布式架构设计、再到海量数据处理、高并发处理、最后到性能优化和调优。上个月,我曾推荐过一个课程,它不仅能帮你解决技术学习的问题,**还能直接内推进大厂,**这门课是拉勾的**《Java工程师高薪训练营》****,**

2301_82243838的博客 1193

怒赞了,阿里P8面试官推荐的Java高并发核心编程文档

学完阿里P8面试官推荐的Java高并发核心编程文档后,终于拿到了蚂蚁p6的offer,这份文档包含的内容有点多。Java高并发核心编程文档《尼恩Java高并发三部曲》获读者怒赞!由浅入深地剖析了高并发IO的底层原理。图文并茂的介绍了TCP、HTTP、WebSocket协议的核心原理。细致深入地揭秘了Reactor高性能模式。全面介绍了Netty框架,并完成单体IM、分布式IM的实战设计。详尽地介绍了ZooKeeper、Redis的使用,以帮助提升高并发、可扩展能力。

架构师尼恩 1898

阿里P9面试官分享:应聘阿里全流程

应聘阿里是一个相对较长的流程,涉及岗位选择,简历投递,简历评估,技术面试,HR面试,背景调查,入职材料准备等环节。其中,关于技术面试,网上有很多优秀的攻略,但普遍聚焦于“纯知识点”总结,而阿里的技术面试并非单纯的知识点问答,单从技术层面做准备并不可取,此外,应聘流程中还有很多需要注意的点。 本场聊聊将从招聘者和面试官的角度,详细解读应聘阿里全流程,主要内容如下: 1.岗位选择与简历投递; 2.初见...

weixin_44946117的博客 5321

Java最全阿里8年技术面试官:这7个些建议能让你受益终身,java面试笔试题初级

各位读者,由于本篇幅度过长,为了避免影响阅读体验,下面我就大概概括了整理了本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录需要这份系统化的资料的朋友,可以点击这里获取+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.youkuaiyun.com/forums/4f45ff00ff254613a03fab5e56a57acb)收录**需要这份系统化的资料的朋友,可以点击这里获取。

2401_83977357的博客 868

作为Java面试官,我会问Java程序员一些什么问题?,一线互联网大厂中高级Java面试真题收录

这份清华大牛整理的进大厂必备的redis视频、面试题和技术文档祝大家早日进入大厂,拿到满意的薪资和职级~~~加油!!!网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!!

2401_84439743的博客 1080
上一篇: 工作8年,第一次这么清醒的理解final关键字?面试官都服了
下一篇: 工作8年的程序员感慨:final、finally、finalize面试这么卷?
编程匠工
博客等级 码龄7年 54粉丝 133原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值