面试题2

  1. 最小连接数法:将请求分配给当前连接数最少的后端服务器,适用于长连接、短连接混合场景。

1.String类可以被继承吗?

在Java中,String类是被声明为final的,这意味着它是不可变的,不可被继承。因为final类不允许其他类继承它,所以String类不能被继承。如果您尝试创建一个继承自String的子类,编译器将会报错

2.0biect类有什么方法? 都用过哪些?

在Java中,所有的类都是直接或间接地继承自Object类。因此,所有的类都会继承Object类中的一些方法。Object类中的一些常用方法包括:

  1. equals(Object obj)方法:用于比较两个对象是否相等。

  2. hashCode()方法:返回对象的哈希码。

  3. toString()方法:返回对象的字符串表示。

  4. getClass()方法:返回对象所属的类。

  5. wait()方法:导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。

  6. notify()方法:唤醒在该对象上等待的单个线程。

  7. notifyAll()方法:唤醒在该对象上等待的所有线程。

路盛通智能科技

3.final的作用

1.定义常量,定以后不能被修改

2.禁止类的继承,加上final关键字后将该类声明为最终类,禁止其他类继承该类

3.禁止方法重写,将该方法声明为最终方法,禁止子类对其进行重写

4.提高性能,例如,JVM在编译时会对final变量进行常量折叠,将其替换为常量值,从而减少程序的运行时间和内存占用。

4.array和list之间的转换

1.数组转换成list:Arrays.asList()  该方法接受一个数组作为参数,并返回一个List对象。例如:

1 String[] array = {"apple", "banana", "orange"};
2 List<String> list = Arrays.asList(array);

2.list转换成数组:list.toArray()  如果希望返回指定类型的数组,则可以使用toArray(T[] a)方法。例如:

List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
String[] array = list.toArray(new String[0]);

4.抽象类和接口的区别

1.实现方式:抽象类使用关键字abstract定义,接口使用关键字interface定义

2.继承关系:抽象类可以被其他类继承,子类需要实现抽象方法。接口可以被其他类实现,实现类需要实现接口中的所有方法

3.多继承支持:Java中一个类只能继承一个父类,但是可以实现多个接口,因此接口支持多继承

4.访问修饰符:抽象类中的抽象方法可以使用publicprotecteddefault修饰符,而接口中的方法只能使用public修饰符。

5.变量定义:抽象类中可以定义成员变量,可以有构造方法,而接口只能定义常量(public static final修饰的变量),不能有构造方法。

5.rabbitmq是什么,应用场景?

rabbitmq是开源消息中间件,主要功能是实现消息的异步传输和处理,它通过消息队列的方式来处理消息,消息的发送者将消息发送到队列中,消息的接收者从队列中获取消息并进行处理。消息队列的优势在于解耦,消息的发送者和接收者之间不直接通信,而是通过消息队列进行中介,从而实现了系统组件之间的解耦。

应用场景:在线商城的订单处理。当一个顾客下单时,订单系统会将订单信息发送到一个RabbitMQ消息队列中。支付系统从队列中获取订单信息并进行支付处理。如果支付成功,则将订单状态修改为已支付,并将订单信息发送到另一个队列中。物流系统从队列中获取订单信息并进行发货处理。当订单状态被修改为已发货时,订单系统会发送通知消息给顾客。这个整个流程中,各个系统通过RabbitMQ消息队列来进行异步通信,从而实现了系统之间的解耦。

6.rabbitmq的组成

  1. Producer(生产者):生产者负责创建并发送消息到RabbitMQ服务器。

  2. Consumer(消费者):消费者负责从RabbitMQ服务器接收并消费消息。

  3. Exchange(交换器):交换器接收生产者发送的消息并按照一定规则将消息路由到队列中。

  4. Queue(队列):队列是消息的存储和转发的地方,消费者从队列中获取消息进行处理。

  5. Binding(绑定):绑定将交换器和队列按照一定的规则绑定起来,从而实现消息的路由。

  6. Virtual Host(虚拟主机):虚拟主机是一种逻辑隔离机制,每个虚拟主机都拥有自己的交换器、队列和绑定。

  7. Connection(连接):连接是客户端与RabbitMQ服务器之间的TCP连接。

  8. Channel(信道):信道是建立在连接之上的虚拟连接,用于完成消息的发送和接收。

7.创建线程的方式

  1. 继承Thread类并重写run()方法:这种方式需要定义一个新的类来继承Thread类,并重写run()方法来定义线程执行的逻辑。然后创建该类的实例,调用start()方法启动线程。

  2. 实现Runnable接口:这种方式需要定义一个实现Runnable接口的类,并实现run()方法来定义线程执行的逻辑。然后创建该类的实例,将其传递给Thread类的构造函数中,调用start()方法启动线程。

  3. 使用线程池:线程池是一种重用线程的机制,它会维护一定数量的线程并使其可重用。通过使用线程池,可以有效地控制线程的数量,避免线程的频繁创建和销毁。

    在Java中,通常使用第2种方式来创建线程,因为它可以避免单继承的限制,并且可以               实现代码的分离,使得代码更加清晰和易于维护。

8.sql的执行顺序

  1. FROM:首先从表中读取数据,这个过程称为“表扫描”。
  2. WHERE:将FROM子句中的结果集中符合WHERE子句中条件的行保留,不符合条件的行丢弃。
  3. GROUP BY:根据GROUP BY子句中的列,将WHERE子句过滤后的结果集进行分组。
  4. HAVING:将GROUP BY子句分组后的结果集再次进行过滤,只保留符合HAVING子句中条件的分组。
  5. SELECT:从GROUP BY和HAVING子句的结果集中选择指定的列进行查询。
  6. DISTINCT:去除查询结果集中重复的行。
  7. ORDER BY:将查询结果集按指定的列进行排序。
  8. LIMIT:返回指定数量的结果行。

需要注意的是,有些SQL数据库执行的顺序可能会略有不同,例如有些数据库可能会在         SELECT之前进行DISTINCT操作。

9.redis的常用数据类型

  1. String(字符串):可以存储任意类型的字符串,包括二进制数据,最大存储容量为512MB。
  2. List(列表):可以存储有序的字符串列表,支持从两端进行数据的插入、读取和删除操作。
  3. Set(集合):可以存储无序的唯一元素集合,支持集合之间的交、并、差等集合运算。
  4. Sorted Set(有序集合):可以存储有序的唯一元素集合,支持按照指定的分值进行排序,支持范围查找和排名查找等操作。
  5. Hash(哈希表):可以存储多个键值对,支持快速地进行单个键值对的读取和修改操作,适用于存储对象或实体属性。
  6. Bitmaps(位图):可以用于存储二进制数据中的位信息,支持位操作,例如并、交、补等操作。

10.redis的删除策略

  1. 定期删除:Redis会周期性地扫描数据库,删除一定时间内未被访问的数据。可以通过配置参数maxmemorymaxmemory-policy来设置Redis的最大内存限制和删除策略。定期删除策略的优点是简单高效,缺点是可能会导致过期数据没有及时删除,浪费内存。
  2. 惰性删除:Redis在访问某个键值对时,先检查其是否过期,如果过期则立即删除。惰性删除策略的优点是可以确保过期数据及时删除,缺点是会增加访问数据的时间复杂度。
  3. 定期删除和惰性删除结合:Redis可以通过结合定期删除和惰性删除策略来优化内存的使用效率。在数据库中设置键的过期时间,同时Redis会定期扫描过期键并删除,避免了过期数据的浪费。

在实际应用中,需要根据实际情况选择合适的删除策略来平衡内存和性能的关系。

11.sql的优化策略

  1. 创建合适的索引:索引可以加快SQL查询的速度,但是过多的索引会降低数据库写入性能。应该根据查询的业务场景和数据分布情况,选择合适的索引类型和建立索引的字段。
  2. 减少查询数据的范围:应该尽量减少查询数据的范围,可以通过添加where条件、使用limit限制返回的结果数等方式来实现。
  3. 避免使用子查询:子查询会增加SQL查询的复杂度和开销,应该尽量避免使用。可以通过关联查询、临时表等方式来替代子查询。
  4. 避免使用SELECT *:应该尽量避免使用SELECT *语句,因为这会查询所有的字段,增加网络传输和数据处理的开销。应该只查询需要的字段,可以减少查询的时间和数据传输的大小。
  5. 避免使用函数和表达式:函数和表达式会增加SQL查询的计算开销,应该尽量避免使用。可以通过预处理和缓存查询结果等方式来优化查询的性能。
  6. 优化SQL语句的执行顺序:应该尽量优化SQL语句的执行顺序,可以通过分解复杂的查询语句、重新组织查询条件等方式来实现。
  7. 使用分区表:当表中数据量很大时,可以将表分成多个分区,分别存储不同的数据范围。这样可以加快查询速度,同时减少锁的竞争,提高并发性能。

SQL优化是一个复杂而又关键的工作,需要深入了解业务场景和数据特征,结合数据库的优化参数和工具,不断优化SQL语句和数据库性能,提高系统的性能和可用性。

12.mysql索引失效的场景

  1. 在索引列上使用函数或表达式,例如使用WHERE YEAR(create_time) = 2021。这种情况下,MySQL无法使用索引,因为它需要计算函数或表达式的值。

  2. 索引列上的数据类型不匹配。例如,如果索引列是整数类型,但是查询时使用了字符串类型的值,那么MySQL将无法使用索引。

  3. 对索引列使用LIKE操作符以模糊匹配。在这种情况下,MySQL只能使用索引的前缀来匹配,因此可能会导致索引失效。

  4. 当使用NOT操作符时,MySQL将无法使用索引。

  5. 在JOIN查询中,如果MySQL无法确定哪个表是驱动表(即哪个表是第一个被查询的表),则可能会导致索引失效。

  6. 在使用OR逻辑操作符时,如果MySQL无法使用索引来覆盖所有OR条件,则可能会导致索引失效。

  7. 如果查询返回的数据太多,MySQL可能会决定不使用索引,而是执行全表扫描。

13.springboot自动配置的原理

Spring Boot 的自动配置原理基于 Spring 的条件化配置和 Spring 的配置元数据。当应用程序启动时,Spring Boot 会扫描类路径上的所有 jar 包,并查找 META-INF/spring.factories 文件,该文件包含了可用的自动配置类。

Spring Boot 的自动配置类通常使用 @Conditional 注解,它可以根据条件来决定是否应该将某个 Bean 注册到应用程序上下文中。这些条件通常基于特定的环境变量、属性值、类路径上的文件存在与否等等。

当应用程序启动时,Spring Boot 将读取应用程序的配置文件并确定哪些自动配置类需要启用,然后将这些自动配置类中定义的 Bean 注册到 Spring 应用程序上下文中。

这种自动配置机制可以大大简化 Spring Boot 应用程序的配置过程,使得开发者可以更加专注于业务逻辑的实现。

14.vue的生命周期函数

  1. beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性。

  2. created:实例已经在内存中创建 OK,此时 data 和 methods 已经创建 OK,此时还没有开始编译模板。

  3. beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中。

  4. mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示。

  5. beforeUpdate:状态更新之前执行此函数,此时 data 中的状态值是最新的,但是界面上的数据还没有更新。

  6. updated:实例更新完毕之后调用此函数,此时 data 中的状态值和界面上的数据都已经完成了更新。

  7. beforeDestroy:实例销毁之前调用。

  8. destroyed:实例销毁之后调用。

在 Vue.js 中,组件的生命周期和 Vue 实例的生命周期是一样的,只是多了几个组件特有的生命周期函数。例如:

  1. beforeRouteEnter:在路由进入该组件前调用。

  2. beforeRouteUpdate:在路由更新该组件前调用。

  3. beforeRouteLeave:在离开当前路由时调用。

15.nginx的配置

# 全局配置
user nginx;  # 指定Nginx进程运行的用户
worker_processes auto;  # 自动设置为处理器的数量
error_log /var/log/nginx/error.log;  # 错误日志文件路径
pid /run/nginx.pid;  # 进程ID文件路径

# 事件模块配置
events {
  worker_connections 1024;  # 每个工作进程最大连接数
}

# HTTP模块配置
http {
  include /etc/nginx/mime.types;  # 包含文件类型配置
  default_type application/octet-stream;  # 默认文件类型
  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';  # 日志格式
  access_log /var/log/nginx/access.log main;  # 访问日志文件路径及格式

  # 虚拟主机配置
  server {
    listen 80;  # 监听端口
    server_name example.com;  # 域名或IP地址

    # 根据不同请求路径或文件类型转发到不同的后端服务器
    location /api/ {
      proxy_pass http://api_server/;
    }
    location / {
      root /var/www/html;  # 静态文件根目录
      index index.html;  # 默认首页文件名
    }
  }
}

在这个配置示例中,Nginx的配置分为全局配置、事件模块配置和HTTP模块配置三部分,其中HTTP模块配置包含了虚拟主机配置、日志配置和转发规则等。虚拟主机配置中指定了监听的端口和服务器名,并且定义了转发规则,将不同的请求路径或文件类型转发到不同的后端服务器。

16.负载均衡的方式

  1. 随机法:请求随机分配给后端服务器,适用于后端服务器配置相同、访问量不大的情况。

  2. 轮询法:将请求轮流分配给后端服务器,适用于后端服务器配置相同、访问量较大的情况。

  3. 加权轮询法:根据后端服务器的性能配置和负载情况进行加权分配,适用于后端服务器配置不同、访问量较大的情况。

  4. 最小连接数法:将请求分配给当前连接数最少的后端服务器,适用于长连接、短连接混合场景。

17.docker的常用命令

  1. docker run:启动一个容器
  2. docker start:启动一个已经停止的容器
  3. docker stop:停止一个容器
  4. docker ps:列出所有正在运行的容器
  5. docker images:列出所有本地镜像
  6. docker rm:删除一个或多个容器
  7. docker rmi:删除一个或多个本地镜像
  8. docker exec:在正在运行的容器中执行命令
  9. docker build:根据Dockerfile构建镜像
  10. docker pull:从远程仓库拉取镜像
posted @ 2023-05-14 20:27  空空大首领  阅读(29)  评论(0编辑  收藏  举报