• 兴业数金一面


    目录

    1、关系型数据库和非关系型数据库的区别

    2、Java中的八大基本数据类型

    3、面向对象的三大特征

    4、SpringBoot常用的注解

    5、MyBatis的${}和#{}的区别?什么情况下使用${}

    6、多线程的实现方式?

    7、Java中如何保证线程安全?

    8、MySQL常见的索引

    9、索引什么时候失效

    10、索引不适合哪些场景    

    11、什么是B+树?


    1、关系型数据库和非关系型数据库的区别

            两者的区别主要在于数据的存储形式不同。像Mysql、Oracle等都是关系型数据库,而Redis、MongoDB都是非关系型数据库。

            关系型数据库的最大特征就是表,对象的属性映射为表的列名,数据按行填充,对数据进行CRUD的时候,都是基于表中的每一行数据进行操作的。

            非关系型数据库的存储方式则是键值对,通过key:value的形式来保存对应的数据。

    2、Java中的八大基本数据类型

            Byte、short、char、int、float、long、double、boolean

    3、面向对象的三大特征

            继承:从已有类中得到继承信息并创建新类的过程,可以使用现有类的所有功能,并且可以在无需重新编写原来类的情况下实现功能的扩展。

            封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象进行操作,对不可信的类进行信息隐藏。

            多态:对于同一个行为,不同的子类对象具有不同的表现形式。一个类实例(对象)的相同方法在不同情形有不同表现形式分为编译时多态(重载)和运行时多态(重写)。

    4、SpringBoot常用的注解

            EnableAutoConfiguration:让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。

            RestController:用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody

            ResponseBody:表示该方法的返回结果直接写入HTTP response body中

            Configuration:指出该类是 Bean 配置的信息源,相当于XML中的,一般加在主类上

         ComponentScan:组件扫描。相当于,如果扫描到有@Component @Controller @Service等这些注解的类,则把这些类注册为bean。

            AutoWired:byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。

            RequestMapping:用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

            Qualifier:当有多个同一类型的Bean时,可以用@Qualifier("name")来指定。与@Autowired配合使用

    5、MyBatis的${}和#{}的区别?什么情况下使用${}

            #{}是预处理,${}是字符串替换。

            Mybatis在处理${}时,会把${}的值替换为变量的值。而Mybatis在处理#{}时,会对SQL语句进行预处理,将#{}的值替换为?,并调用PreparedStatement的set方法进行赋值。

            使用#{}可以防止SQL注入,提高系统的安全性。尽管$不安全,但是它可以解决一些特殊情况下的问题。如:表名作参数时用 ${}。如:select * from ${tableName}、order by 时用 ${}。如:select * from t_user order by ${columnName}。

    6、多线程的实现方式?

    (1)继承Thread类,重写run方法

    1. class MyThread extends Thread{
    2. @Override
    3. public void run() {
    4. System.out.println(Thread.currentThread().getName() + "正在执行");
    5. }
    6. }
    7. public class Day {
    8. public static void main(String[] args) {
    9. MyThread mt = new MyThread();
    10. mt.start();
    11. System.out.println(Thread.currentThread().getName() + "正在执行");
    12. }
    13. }

    执行结果:

      

    (2)实现Runnable接口,重写run方法

    1. class MyThread implements Runnable{
    2. @Override
    3. public void run() {
    4. System.out.println(Thread.currentThread().getName() + "正在执行");
    5. }
    6. }
    7. public class Day {
    8. public static void main(String[] args) {
    9. MyThread mt = new MyThread();
    10. Thread thread = new Thread(mt);
    11. thread.start();
    12. System.out.println(Thread.currentThread().getName() + "正在执行");
    13. }
    14. }

     执行结果:

     

     (3)实现Callable接口,重写call方法

    1. class MyThread implements Callable {
    2. @Override
    3. public String call() {
    4. System.out.println(Thread.currentThread().getName() + "正在执行");
    5. return "success";
    6. }
    7. }
    8. public class Day {
    9. public static void main(String[] args) throws ExecutionException, InterruptedException {
    10. Callable callable = new MyThread();
    11. FutureTask futureTask = new FutureTask<>(callable);
    12. Thread thread = new Thread(futureTask);
    13. thread.start();
    14. System.out.println("Callable接口的返回值" + futureTask.get());
    15. System.out.println(Thread.currentThread().getName() + "正在执行");
    16. }
    17. }

    执行结果:

     (4)使用线程池

    1. public class Day {
    2. public static void main(String[] args) throws ExecutionException, InterruptedException {
    3. ExecutorService threadPool = Executors.newCachedThreadPool();
    4. try {
    5. for (int i = 0; i < 5; i++) {
    6. threadPool.execute(()->{
    7. System.out.println(Thread.currentThread().getName() + "正在执行");
    8. });
    9. }
    10. } catch (Exception e) {
    11. e.printStackTrace();
    12. } finally {
    13. threadPool.shutdown();
    14. }
    15. }
    16. }

     执行结果:

     

    7、Java中如何保证线程安全?

            Java保证线程安全的方式有很多,其中较为常用的有三种,按照资源占用情况由轻到重排列,这三种保证线程安全的方式分别是原子类、volatile、锁。

            原子类(JUC):JDK从1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。在atomic包里一共提供了17个类,按功能可以归纳为4种类型的原子更新方式,分别是原子更新基本类型、原子更新引用类型、原子更新属性、原子更新数组。无论原子更新哪种类型,都要遵循“比较和替换”规则,即比较要更新的值是否等于期望值,如果是则更新,如果不是则失败。

            volatile:是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”以及防止指令重排序,从而可以保证单个变量读写时的线程安全。可见性问题是由处理器核心的缓存导致的,每个核心均有各自的缓存,而这些缓存均要与内存进行同步。volatile具有如下的内存语义:当写一个volatile变量时,该线程本地内存中的共享变量的值会被立刻刷新到主内存;当读一个volatile变量时,该线程本地内存会被置为无效,迫使线程直接从主内存中读取共享变量。

            锁:原子类和volatile只能保证单个共享变量的线程安全,锁则可以保证临界区内的多个共享变量的线程安全,Java中加锁的方式有两种,分别是synchronized关键字和Lock接口。synchronized是比较早期的API,在设计之初没有考虑到超时机制、非阻塞形式,以及多个条件变量。若想通过升级的方式让它支持这些相对复杂的功能,则需要大改它的语法结构,不利于兼容旧代码。因此,JDK的开发团队在1.5新增了Lock接口,并通过Lock支持了上述的功能,即:支持响应中断、支持超时机制、支持以非阻塞的方式获取锁、支持多个条件变量(阻塞队列)。

            除了以上三种方式外以外,juc包下还提供了一些线程同步工具类,如CountDownLatch(允许一个或多个线程等待其他线程完成操作)、Semaphore(信号量,可以控制同时访问特定资源的线程数量)等等.

            我们也可以考虑使用ThreadLocal存储变量,ThreadLocal可以很方便地为每一个线程单独存一份数据,也就是将需要并发访问的资源复制成多份。这样一来,就可以避免多线程访问共享变量了,它们访问的是自己独占的资源,它从根本上隔离了多个线程之间的数据共享。

    8、MySQL常见的索引

            索引时对数据库表的一列或者多列的值进行排序的一种结构,使用索引可以快速访问数据表中的特定信息,常见的索引有以下几种:

    普通索引:是基本的索引类型,可以为Null,可以有多个

    主键索引:数据列不能重复,不能为Null,一个表上只有一个主键索引

    组合索引:由多个列值组成的索引,既可以创建普通索引,也可以创建唯一索引。

    唯一索引:数据列不允许重复,可以为Null,索引列的值必须是唯一的

    全文索引:对文本的内容进行索引,在数据量大时取代like+%。

    空间索引:对空间数据累心的字段建立索引,该列不能为空

    9、索引什么时候失效

    条件中有or,例如select * from table_name where a = 1 or b = 3

    在索引上进行计算会导致索引失效,例如select * from table_name where a + 1 = 2

    在索引的类型上进行数据类型的隐形转换,会导致索引失效,例如字符串一定要加引号,假设 select * from table_name where a = '1'会使用到索引,如果写成select * from table_name where a = 1则会导致索引失效。

    在索引中使用函数会导致索引失效,例如select * from table_name where abs(a) = 1

    在使用like查询时以%开头会导致索引失效

    索引上使用!、=、<>进行判断时会导致索引失效,例如select * from table_name where a != 1

    索引字段上使用 is null/is not null判断时会导致索引失效,例如select * from table_name where a is null

    mysql估计使用全表扫描要比使用索引快,则不使用索引。

    10、索引不适合哪些场景    

             对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

            对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度

            对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。

            当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能

    11、什么是B+树?

            B+ 树是是一个n叉树,每个节点通常有多个孩子,一颗B+树包含根节点、内部节点和叶子节点。B+ 树通常用于数据库和操作系统的文件系统中。 在B+树中,所有的记录节点都是按照键值大小的顺序存放在叶子节点上。

  • 相关阅读:
    SIFT和SURF的差异已经使用场景分析
    【DataV/echarts】vue中使用,修改地图和鼠标点击部分的背景色
    Vue通知提醒框(Notification)
    文件拷贝【 使用字节流完成文件的复制(支持一切文件类型的复制)】
    嵌入式硬件VS软件,到底哪个更难?
    编译安装gcc-11及可能遇到的bug
    【YOLO系列】YOLOv9论文超详细解读(翻译 +学习笔记)
    笔记36:CNN的多通道卷积到底是什么样的
    Llama模型家族训练奖励模型Reward Model技术及代码实战(三) 使用 TRL 训练奖励模型
    鸿蒙 游戏来了 鸿蒙版 五子棋来了 我不允许你不会
  • 原文地址:https://blog.csdn.net/weixin_47382783/article/details/126239853