前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >招银网络 一面

招银网络 一面

作者头像
田维常
发布2023-10-25 09:53:24
2210
发布2023-10-25 09:53:24
举报

大家好,我是老田

前段时间,一位同学给我反馈的招银网络一面面经,今天来写一下参考答案。

说说你对多态的理解

Java多态是指同一个方法名可以被不同的对象调用,并且根据对象的不同,会自动选择合适的方法进行调用。多态是面向对象编程的重要特性之一。

在Java中,多态实现的关键是继承和方法重写。当一个子类继承自父类,并重写了父类的方法时,可以通过父类的引用指向子类的对象,并调用重写后的方法。这样,无论父类引用指向的是父类对象还是子类对象,都可以调用到合适的方法,实现多态。

多态的好处在于增加了代码的灵活性和可扩展性。通过多态,可以编写出更通用、更灵活的代码,减少了代码的重复编写。当需要新增一个子类时,只需要继承父类并重写相应的方法即可,而不需要修改已有的代码。

另外,多态还可以实现接口的统一调用。当多个类实现了同一个接口时,可以使用接口的引用指向不同的实现类对象,通过接口调用方法,实现了对不同类对象的统一调用。

总结来说,Java多态是通过继承和方法重写实现的,可以提高代码的灵活性和可扩展性,实现了对不同类对象的统一调用。

用java手写生产者消费者

生产者消费者模型是一种解决多线程间数据交换的经典模式。在该模型中,生产者负责生产数据并放入共享的缓冲区中,而消费者则负责从缓冲区中取出数据进行消费。

以下是使用Java手写生产者消费者模型的示例:

代码语言:javascript
复制
import java.util.LinkedList;
/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * 博客地址:<a href="http://woaijava.cc/">博客地址</a>
 * 生产者与消费者案例
 */
public class ProducerConsumer {

    private LinkedList<Integer> buffer = new LinkedList<>();
    private int capacity = 5;

    public void produce() throws InterruptedException {
        int value = 0;
        while (true) {
            synchronized (this) {
                while (buffer.size() == capacity) {
                    wait();
                }
                System.out.println("Producer produced: " + value);
                buffer.add(value++);
                notify();
                Thread.sleep(1000);
            }
        }
    }

    public void consume() throws InterruptedException {
        while (true) {
            synchronized (this) {
                while (buffer.isEmpty()) {
                    wait();
                }
                int value = buffer.removeFirst();
                System.out.println("Consumer consumed: " + value);
                notify();
                Thread.sleep(1000);
            }
        }
    }

    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();

        Thread producerThread = new Thread(() -> {
            try {
                pc.produce();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread consumerThread = new Thread(() -> {
            try {
                pc.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producerThread.start();
        consumerThread.start();
    }
}

在这个例子中,我们使用了一个LinkedList作为共享的缓冲区,使用synchronized关键字保证了线程安全。

生产者的produce方法不断地往缓冲区中添加数据,如果缓冲区已满,则调用wait()方法将生产者线程阻塞,等待消费者消费数据后唤醒。在往缓冲区中添加数据后,调用notify()方法唤醒消费者线程。

消费者的consume方法不断地从缓冲区中取出数据进行消费,如果缓冲区为空,则调用wait()方法将消费者线程阻塞,等待生产者生产数据后唤醒。在消费完数据后,调用notify()方法唤醒生产者线程。

在生产者和消费者模式中我们应该注意以下几点:

  1. 生产者和消费者必须共享同一个缓冲区,以实现数据交换。
  2. 使用synchronized关键字确保对缓冲区的访问是线程安全的,避免出现竞态条件。
  3. 使用wait()和notify()方法进行线程间的通信,保证生产者和消费者能够正确地阻塞和唤醒。
  4. 在生产者和消费者的方法中使用while循环判断条件,而不是使用if语句,以避免虚假唤醒的问题。
  5. 在生产者和消费者的方法中使用sleep()方法进行简单的模拟,以便观察效果。在实际应用中,可以根据需求进行相应的处理。
SQL查询语句执行流程

在MySQL中,一条查询SQL的执行流程可以分为以下几个步骤:

  1. 语法解析:MySQL首先对查询SQL进行语法解析,检查SQL语句的语法是否正确。如果SQL语句存在语法错误,MySQL将返回相应的错误信息。
  2. 语义解析:语法解析通过后,MySQL会对查询SQL进行语义解析,即根据SQL语句的语法结构和语义规则,确定查询的执行计划。在这个步骤中,MySQL会检查表、列的存在性,以及对应的权限等。
  3. 查询优化器:在语义解析之后,MySQL会通过查询优化器对查询进行优化,以确定最佳的执行计划。查询优化器会考虑多种因素,如索引的使用、连接的顺序、子查询的优化等。优化器会生成多个可能的执行计划,并通过成本估算器来评估每个执行计划的代价,选择代价最低的执行计划。
  4. 执行计划生成:查询优化器确定最佳的执行计划后,MySQL会根据该执行计划生成实际的执行代码。执行计划包括了具体的操作,如表的扫描、索引的使用、连接、过滤条件的判断等。
  5. 执行查询:生成执行计划后,MySQL会执行查询操作。执行查询的过程中,MySQL会根据执行计划逐步执行各个操作,并将结果存储在临时表或内存中。
  6. 结果返回:查询执行完毕后,MySQL会将查询结果返回给客户端。如果查询结果较大,MySQL可能会使用分页等技术将结果分批返回。

需要注意的是,以上步骤是一个大致的流程,实际执行过程中可能会有一些细微的差别。此外,MySQL还有一些高级特性,如并发控制、事务处理等,也会影响查询的执行流程。

Mybatis用到了哪些设计模式?

Mybatis框架中使用了以下设计模式:

  1. 生成器模式(Builder Pattern):Mybatis使用了构建器模式来构建SqlSessionFactory。SqlSessionFactoryBuilder类提供了一系列方法来配置Mybatis并最终构建SqlSessionFactory实例。
  2. 代理模式(Proxy Pattern):Mybatis使用了动态代理来生成Mapper接口的实现类。MapperProxy类实现了InvocationHandler接口,并在invoke方法中执行SQL语句。
  3. 工厂模式(Factory Pattern):Mybatis使用了工厂模式来创建不同的对象。例如,SqlSessionFactoryBuilder类用于创建SqlSessionFactory实例,SqlSessionFactory类用于创建SqlSession实例。
  4. 注解模式(Annotation Pattern):Mybatis使用了注解来映射SQL语句和Java方法。例如,@Select、@Insert、@Update和@Delete等注解用于标记方法并指定对应的SQL语句。
  5. 模板模式(Template Pattern):Mybatis使用了模板模式来定义了一些基本操作的算法骨架,具体的实现由用户进行定制。例如,BaseExecutor类定义了数据库操作的基本流程,而具体的执行逻辑由子类实现。
  6. 单例模式(Singleton Pattern):Mybatis中的SqlSessionFactory和MapperRegistry等类都采用了单例模式来保证全局唯一的实例。
  7. 装饰器模式(Decorator Pattern):Mybatis使用了装饰器模式来增强对象的功能。例如,Executor接口的实现类可以通过装饰器模式来增加缓存、日志等功能。

总结:Mybatis框架中使用了生成器模式、代理模式、工厂模式、注解模式、模板模式、单例模式和装饰器模式等多种设计模式。这些设计模式使得Mybatis具有灵活、可扩展和可定制的特性。

HashMap,HashTable,ConcurrentHashmap区别

三者区别如下:

  1. 线程安全性
    • HashMap:非线程安全,多线程环境下需要自行保证同步。
    • HashTable:线程安全,使用synchronized关键字保证线程安全。
    • ConcurrentHashMap:线程安全,使用了锁分段技术(Segment),每个Segment相当于一个小的HashTable,不同的Segment可以被不同的线程同时访问,从而提高并发性能。
  2. 锁粒度
    • HashMap:无锁,不保证线程安全,适用于单线程环境。
    • HashTable:使用全局锁,对整个HashTable进行加锁,性能较差。
    • ConcurrentHashMap:使用锁分段技术,每个Segment都有一个独立的锁,不同的线程可以同时访问不同的Segment,提高了并发性能。
  3. 数据结构
    • HashMap:数组+链表+红黑树,当链表长度超过阈值(默认为8)时,链表转换为红黑树,提高查询效率。
    • HashTable:数组+链表,没有红黑树优化。
    • ConcurrentHashMap:数组+链表+红黑树,与HashMap类似,但每个Segment都是一个小的HashTable,Segment内部结构与HashMap相同。
  4. 扩容机制
    • HashMap:当元素个数超过容量的75%时,进行扩容,扩容为原来的两倍。
    • HashTable:当元素个数超过容量的75%时,进行扩容,扩容为原来的两倍加一,并且要求扩容后的容量是一个素数。
    • ConcurrentHashMap:当元素个数超过容量的75%时,进行扩容,扩容为原来的两倍。

总结:HashMap是非线程安全的,HashTable是线程安全的但性能较差,ConcurrentHashMap是线程安全且并发性能较好的。在多线程环境下,推荐使用ConcurrentHashMap,而在单线程环境下,推荐使用HashMap。

内存泄漏的情况有哪些?

以下是一些可能会导致内存泄漏的场景:

  1. 对象的生命周期超出了其实际使用范围:如果创建的对象没有被正确释放或销毁,它们将继续占用内存直到应用程序结束。
  2. 长生命周期的对象引用短生命周期的对象:如果长生命周期的对象持有对短生命周期对象的引用,即使短生命周期对象不再使用,它们也不会被垃圾收集器回收。
  3. 集合类对象的使用不当:如果集合类对象(如List、Map等)在使用过程中没有正确地清除不再需要的元素,这些元素将继续占用内存。
  4. 资源未正确关闭:如果在使用资源(如文件、数据库连接、网络连接等)后没有正确关闭它们,将导致资源泄漏。
  5. 缓存使用不当:如果缓存对象没有正确管理,即没有删除过期的缓存或缓存的大小没有限制,将导致内存泄漏。
  6. 事件监听器未正确移除:如果注册的事件监听器没有在不再需要时正确地移除,它们会继续保持对对象的引用,导致内存泄漏。
  7. 多线程内存泄漏:如果多线程中的线程没有正确地结束或资源没有正确释放,将导致内存泄漏。

以上只是一些常见的场景,实际上内存泄漏可能发生在许多其他情况下。为了避免内存泄漏,我们应该注意正确地管理对象的生命周期,及时释放不再需要的资源,并确保使用合适的数据结构和算法来优化内存使用。

classpath,path的区别

在Java项目中,classpathpath是两个不同的概念。

  1. classpathclasspath是指Java程序在运行时搜索类、接口和资源文件的路径。当Java程序需要加载类或资源时,它会在classpath下搜索相应的文件。classpath可以包含多个路径,路径之间使用分隔符(如Windows下使用分号,Unix/Linux下使用冒号)分隔。classpath可以设置为文件系统中的目录或JAR文件。
  2. pathpath是操作系统环境变量,用于指定系统在命令行下搜索可执行文件的路径。当在命令行中输入一个可执行文件名时,操作系统会在path路径下搜索相应的可执行文件。path也可以包含多个路径,路径之间使用与classpath相同的分隔符。

区别:

  • classpath是Java程序在运行时搜索类和资源文件的路径,而path是操作系统在命令行下搜索可执行文件的路径。
  • classpath用于Java程序,而path用于操作系统。
  • classpath可以包含多个路径,路径之间使用分隔符分隔,而path也可以包含多个路径,路径之间使用与classpath相同的分隔符。
  • classpath可以设置为文件系统中的目录或JAR文件,而path指定的是可执行文件的路径。

总结:classpath和path是两个不同的概念,用于不同的目的,但它们的用法和设置方式相似。

JVM运行过程

JVM(Java虚拟机)是Java程序的运行环境,它可以解释执行Java字节码,并提供了内存管理、垃圾回收、线程管理等功能。

JVM的运行过程可以分为以下几个步骤:

  1. 加载:JVM会通过类加载器加载Java字节码文件(.class文件)到内存中。类加载器会根据类的全限定名找到对应的字节码文件,并将字节码文件解析成JVM能够理解的内部数据结构。
  2. 验证:在加载完字节码文件后,JVM会对它进行验证,以确保字节码的安全性和正确性。验证过程包括类型检查、字节码验证、符号引用验证等。
  3. 准备:在准备阶段,JVM会为类的静态变量分配内存,并初始化为默认值。例如,对于整型变量,JVM会将其初始化为0。
  4. 解析:在解析阶段,JVM会将类、接口、字段和方法的符号引用解析为直接引用。符号引用是一种能够唯一标识类、接口、字段和方法的描述符,而直接引用则是指向内存中实际对象的指针。
  5. 初始化:在初始化阶段,JVM会执行类的静态初始化代码。静态初始化代码块会按照顺序执行,并初始化静态变量。如果一个类有父类,那么会先初始化父类,再初始化子类。
  6. 执行:在执行阶段,JVM会按照字节码的指令序列一条一条地执行。字节码指令包括加载、存储、运算、跳转、方法调用等操作。JVM会维护一个栈帧栈来保存方法的局部变量、操作数栈和方法返回值。
  7. 垃圾回收:JVM会定期进行垃圾回收,释放不再使用的内存。垃圾回收器会标记和清理不再使用的对象,并将它们的内存回收。
  8. 异常处理:在执行过程中,如果发生异常,JVM会根据异常处理表(Exception Table)来查找对应的异常处理代码,并执行相应的异常处理逻辑。
  9. 程序结束:当程序执行完毕或遇到System.exit()方法时,JVM会终止程序的执行,并释放所有资源。

总之,JVM的运行过程包括加载、验证、准备、解析、初始化、执行、垃圾回收、异常处理和程序结束等阶段。这些阶段相互协作,使得Java程序能够在JVM上运行。

讲一讲GC机制

JVM(Java虚拟机)的垃圾回收(Garbage Collection)机制是自动管理和释放不再使用的内存对象。它通过检测不再被引用的对象,并将其回收来优化内存的使用。

VM的GC机制有多种实现方式(垃圾收集算法),其中比较常见的有以下几种:

  1. 标记-清除算法Mark-Sweep):标记阶段和垃圾回收阶段分开进行。首先标记出所有的活动对象,然后清除所有的垃圾对象。这种算法的缺点是会产生内存碎片。
  2. 复制算法Copying):将堆内存分为两个相等的部分,每次只使用其中一部分。当垃圾回收时,将活动对象复制到另一部分,并清除原来的部分。这种算法的优点是不会产生内存碎片,但缺点是只能使用堆内存的一半。
  3. 标记-整理算法Mark-Compact):标记阶段和整理阶段一起进行。首先标记出所有的活动对象,然后将活动对象向一端移动,然后清除剩余的内存空间。这种算法可以解决内存碎片问题。
  4. 分代算法Generational):根据对象的生命周期将堆内存划分为不同的区域,每个区域使用不同的垃圾回收算法。一般将新创建的对象放入年轻代,使用复制算法进行回收;将存活时间较长的对象放入老年代,使用标记-整理算法进行回收。

总的来说,JVM的垃圾回收机制是通过标记不再被引用的对象,并将其清除或整理来释放内存空间。不同的GC算法和策略可以根据应用程序的需求进行选择和调优。

阻塞队列
start()方法和run()方法的区别,可以多次调用start()方法吗?

Thread的start()方法用于启动一个新线程,并JVM会回调线程的run()方法。当调用start()方法时,会创建一个新的线程,并在新的线程中执行run()方法。

而run()方法是Thread类中定义的一个普通方法,用于线程的具体执行逻辑。

可以多次调用start()方法吗?不可以,调用start()方法会启动一个新的线程,如果多次调用start()方法,会抛出IllegalThreadStateException异常。每个线程只能启动一次,多次调用会导致不可预料的结果。如果要多次执行线程的逻辑,可以将线程的逻辑封装到一个方法中,然后通过多次调用该方法来实现。

说说线程池原理

Java线程池是一种管理和复用线程的机制,它能够提高程序的效率和性能。线程池中包含一个线程队列和一些管理线程的组件,当需要执行任务时,可以从线程池中获取一个空闲线程来执行任务。

Java线程池的原理如下:

  1. 创建线程池:通过ThreadPoolExecutor类创建线程池,可以指定线程池的大小、任务队列和拒绝策略等参数。
  2. 提交任务:将任务提交给线程池,线程池会根据自身的状态和参数来决定是直接执行任务、放入队列或者拒绝任务。
  3. 执行任务:线程池中的线程从任务队列中获取任务,并执行任务。
  4. 线程复用:当线程执行完任务后,并不会立即销毁,而是会继续等待执行新的任务,以复用线程,减少线程的创建和销毁开销。
  5. 线程管理:线程池会管理线程的状态、数量和生命周期。可以根据需要动态调整线程池的大小,增加或减少线程的数量。
  6. 任务队列:线程池中的任务队列用于存储待执行的任务,可以是有界队列或无界队列,根据不同的需求选择不同的队列实现。
  7. 拒绝策略:当任务队列已满并且线程池中的线程数达到最大值时,新提交的任务会被拒绝执行。可以通过设置拒绝策略来处理这种情况,如抛出异常、丢弃任务或者调用者自己执行任务。

通过使用线程池,可以减少线程的创建和销毁开销,提高线程的复用性,避免线程数量过多导致系统资源耗尽的问题,从而提高程序的性能和效率。

代理模式和装饰器模式有什么区别?

代理模式和装饰器模式是两种不同的设计模式,虽然它们有一些共同的特点,但是在使用方式和实现上有一些区别。

区别如下:

目的不同 :代理模式的主要目的是为了控制对对象的访问,而装饰器模式的主要目的是为了给对象添加额外的功能。

关注点不同 :代理模式关注于对对象的访问进行控制和管理,装饰器模式关注于对对象的功能进行增强。

涉及的类不同:代理模式通常涉及到三个角色,即接口、代理类和被代理类,而装饰器模式通常只涉及一个接口和多个装饰器类。

功能增强方式不同:代理模式通过在代理类中调用被代理类的方法实现功能增强,而装饰器模式通过在装饰器类中调用被装饰对象的方法,并在其前后添加额外的功能实现功能增强。

相关面经:

16k面试中的10个问题

猫眼 面经和答案

顺丰科技面试

合奥科技 面经

途虎 面经,其实挺简单的!

推荐

MySQL 开发规范,非常详细,建议收藏!

16k面试中的10个问题

从0开始搭建公司技术栈,yyds

简历写成这样,CTO会主动联系你

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术全栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 说说你对多态的理解
  • 用java手写生产者消费者
  • SQL查询语句执行流程
  • Mybatis用到了哪些设计模式?
  • HashMap,HashTable,ConcurrentHashmap区别
  • 内存泄漏的情况有哪些?
  • classpath,path的区别
  • JVM运行过程
  • 讲一讲GC机制
  • 阻塞队列
  • start()方法和run()方法的区别,可以多次调用start()方法吗?
  • 说说线程池原理
  • 代理模式和装饰器模式有什么区别?
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档