随笔录--并发与并行

其他相关问题

如何查看 MySQL 服务被多少个客户端连接了?

  mysql> show processlist;

空闲连接会一直占用着吗?

  • 空闲连接的最大空闲时长,由 wait_timeout 参数控制的
  • 查询命令
mysql> show variables like 'wait_timeout';

  • 手动断开
mysql> kill connection +6;

MySQL 的连接数有限制吗?

MySQL 服务支持的最大连接数由 max_connections 参数控制。

MySQL 的连接也跟 HTTP 一样,有短连接和长连接的概念。

怎么解决长连接占用内存的问题?

  • 定期断开长连接
  • 客户端主动重置连接
第二步:查询缓存

过程

解析出 SQL 语句的第一个字段,看看是什么类型的语句。

如果 SQL 是查询语句(select 语句),MySQL 就会先去查询缓存( Query Cache )里查找缓存数据。

如果查询的语句命中查询缓存,那么就会直接返回 value 给客户端。

如果查询的语句没有命中查询缓存中,那么就要往下继续执行,等执行完后,查询的结果就会被存入查询缓存中。

缺点

  • 更新比较频繁的表,查询缓存的命中率很低

版本变动

  • MySQL 8.0 版本直接将查询缓存删掉了,也就是说 MySQL 8.0 开始,执行一条 SQL 查询语句,不会再走到查询缓存这个阶段了。对于 MySQL 8.0 之前的版本,如果想关闭查询缓存,我们可以通过将参数 query_cache_type 设置成 DEMAND。

这里说的查询缓存是 server 层的,也就是 MySQL 8.0 版本移除的是 server 层的查询缓存,并不是 Innodb 存储引擎中的 buffer pool。

第三步:解析 SQL

过程

  1. 词法分析
  2. 语法分析
  3. 语法不对,解析器就会给报错

注意:表不存在或者字段不存在,并不是在解析器里做的,解析器只负责构建语法树和检查语法,但是不会去查表或者字段存不存在。

第四步:执行 SQL

过程

  1. prepare 阶段,也就是预处理阶段;
  2. optimize 阶段,也就是优化阶段;
  3. execute 阶段,也就是执行阶段;

1 预处理器

检查 SQL 查询语句中的表或者字段是否存在;

将 select * 中的 * 符号,扩展为表上的所有列;

2 优化器

优化器主要负责将 SQL 查询语句的执行方案确定下来

比如在表里面有多个索引的时候,优化器会基于查询成本的考虑,来决定选择使用哪个索引。

要想知道优化器选择了哪个索引,我们可以在查询语句最前面加个 explain 命令

3 执行器

执行器就会和存储引擎交互了,交互是以记录为单位的。

三种方式执行过程

  • 主键索引查询
  • 全表扫描
  • 索引下推(MySQL 5.6 推出的查询优化策略)

特点

  • 执行器查询的过程是一个 while 循环
  • Server 层每从存储引擎读到一条记录就会发送给客户端,之所以客户端显示的时候是直接显示所有记录的,是因为客户端是等查询语句查询完成后,才会显示出所有的记录

总结

执行一条 SQL 查询语句,期间发生了什么?

  • 连接器:建立连接,管理连接、校验用户身份;

  • 查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;

  • 解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;

  • 执行 SQL:执行 SQL 共有三个阶段:

    • 预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。
    • 优化阶段:基于查询成本的考虑,选择查询成本最小的执行计划;
    • 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;

图片

连接器:客户端首先进行身份验证,如果没通过直接返回。

查询缓存:如果身份验证不通过则查询缓存。缓存这个原理很容易理解,就是把常用的数据放到更高效的地方便于查询。查询缓存也有缺点,就是每当数据更改的时候就要重新设置缓存,在 MySQL8.0 已经将查询缓存去掉。

分析器:分析器先会做“词法分析”。把你输入的内容进行识别,知道字符分别代表什么,有什么含义 然后进行语法分析,如果你的 SQL 语句不符合 MySQL 语法就会收到错误提醒。

优化器:优化器作用就是决定使用哪个索引,决定 join 表的连接顺序。优化器会选择它自己认为最高效的方案,(也代表它不一定能选择出最优的方案)。

执行器:执行器还是先会判断有没有执行的权限,如果有权限的话才会执行下一步。遍历满足条件的行,并把组成的记录集作为结果集返回给客户端。

题目二

什么是 IOC,简单讲一下 Spring IOC 的实现机制?

IOC (Inversion of Control),中文翻译为控制反转,是一种编程思想,它将程序中对象的创建、组装、管理等控制权从代码中转移到框架中,实现了松耦合可重用性的设计。

Spring IOC 是 Spring 框架的一个核心特性,它的实现机制主要包括以下几个步骤:

  • 定义 Bean:在 Spring IOC 中,所有的对象都被看作是 Bean,需要在配置文件或者使用注解的方式中进行定义和配置。
  • 创建 Bean 工厂:在 Spring 中,Bean 工厂负责管理 Bean 的创建、组装和销毁等任务。Spring IOC 容器就是 Bean 工厂的一种实现。
  • 读取配置文件:Spring IOC 容器会读取配置文件或者使用注解的方式来获取 Bean 的定义和配置信息。
  • 创建 Bean 实例:Spring IOC 容器根据配置文件中的信息,使用反射技术来创建 Bean 实例,并将其保存在容器中。
  • 组装 Bean:Spring IOC 容器根据配置文件中的信息,将不同的 Bean 实例组装起来,形成一个完整的应用程序。
  • 注入依赖:Spring IOC 容器根据配置文件中的信息,自动为 Bean 注入依赖的对象或者值。
  • 提供 Bean 实例:应用程序通过 Spring IOC 容器获取需要的 Bean 实例,从而使用其中的方法和属性等。

需要注意的是,Spring IOC 还提供了多种作用域,例如单例、原型、会话、请求等作用域,可以根据具体的需求来选择。

同时,Spring IOC 容器也支持 AOP、事务管理等功能,可以为应用程序提供更完整的服务。

什么是IOC容器,以及IOC的创建过程

基本概念

  • IOC(Inverse Of Controll,控制反转):就是原来代码里面需要自己手动创建的对象,依赖,反转给 Spring 来帮忙实现。我们需要创建一个容器,同时需要一种描述来让容器知道要创建的对象与对象之间的关系。
  • 在 Spring 中 BeanFactory 就是 IOC 容器,在 Spring 初始化的时候,创建容器,并将需要创建对象和对象的关系(xml,注解)通过 BeanDefinitionReader 加载到 BeanDefinition 中并保存在 BeanDefinitionMap 中,然后再由 IOC 容器创建 bean 对象.

两种 bean 的注册方式

  • 方法1:通过 @Bean + @Configuration 的方式直接定义要创建的对象与对象的关系
  • 方式2:通过 @Component 定义类,这种方式必须使用 @ComponetScan 定位 Bean 扫描路径

IOC的创建

  • 在 Spring 中 BeanFactory 就是 IOC 容器,在 Spring 初始化的时候,创建容器,并将需要创建对象和对象的关系(xml,注解)通过 BeanDefinitionReader 加载到 BeanDefinition 中并保存在 BeanDefinitionMap 中,在这个过程中会让 BeanDefinitionProcesser(Bean 的定义信息的后置处理器)进行增强,然后再由 IOC 容器创建 bean 对象.

Bean的生命周期(面试官顺着问题往下问的拓展)

  • bean 的实例化:spring 启动后,会查找和加载需要被 spring 管理的 Bean,并且实例化

  • bean 的属性注入(bean 的初始化):bean 被实例化后将 Bean 的引用和值注入到 bean 的属性中

    • 查看是否调用一些 aware 接口,比如 BeanFactoryAware,BeanFactoryAware,ApplicationContextAware 接口,分别会将 Bean 的名字,BeanFactory 容器实例,以及 Bean 所在的上下文引用传入给 Bean
    • 在初始化之前,会查看是否调用了 BeanPostProcessor 的预初始化方法,可以对 bean 进行扩展
    • 调用 InitializingBean 的 afterPropertiesSet()方法:如果 Bean 实现了 InitializingBean 接口,spring 将调用他们的afterPropertiesSet()方法,类似的,如果 Bean 使用 init-method 生命了初始化方法的话,这个方法也会被调用。
    • 初始化成功之后,会查看是否调用 BeanPostProcessor 的初始化后的方法:如果 Bean 实现了 BeanPostProcessor 接口,spring 就将调用他们的 postprocessAfterInitialization()方法。可以对 bean 进行扩展
  • bean的正常使用:可以被应用程序正常使用了,他们将驻留在上下文中,直到应用的上下文被销毁

  • bean的销毁:调用 DisposableBean 的destory()方法:如果 Bean 实现 DisposableBean 接口,spring 将用他的 destory()方法,相同的,如果 Bean 使用了 destory-method 生命销毁方法,该方法也会被调用。(但由于 bean 也分为单例和多例,单例 bean 会随着 IOC 容器的销毁而销毁,多例的 bean 不会随着 IOC 容器的销毁而销毁,他是通过 JVM 里面的垃圾回收器负责回收)

题目三

并发和并行有什么区别?同步和异步有什么区别?

并发并行是两个计算机领域中经常被提到的概念,它们的含义有所不同。

  • 并发(Concurrency):指的是系统中同时存在多个正在执行的任务,并且这些任务之间可能会相互影响。并发通常用来处理多个任务共享资源的情况。在单核 CPU 上,多个任务会轮流使用 CPU 时间片,表现为看似同时执行的情况,但实际上只有一个任务正在执行。
  • 并行(Parallelism):指的是系统中同时存在多个并且相互独立的任务,并且这些任务可以在多个处理器上同时执行,真正意义上的同时处理多个任务。
  • 同步(Synchronous):指的是程序按照代码的顺序执行,一行一行地执行,直到当前行执行完成后才能继续执行下一行。同步通常会阻塞调用者,直到任务完成才能返回。
  • 异步(Asynchronous):指的是程序在执行某个任务时,不会一直等待任务完成,而是继续执行下一行代码,当任务完成后再进行相应的处理。异步通常不会阻塞调用者,可以提高系统的并发性能

总的来说,"并发"和"并行"是针对多个任务的执行方式,"同步"和"异步"是针对任务执行的阻塞方式和返回方式。在实际应用中,可以根据不同的需求来选择合适的并发和同步方式,以提高系统的性能和可靠性。

图片

先介绍并发和并行的区别:

并发:指多个任务同时在执行,但是它们并不是在同一时刻执行,而是通过快速切换上下文来模拟同时执行,优秀的并发可以无限逼近并行,但无法完全做到并行。

例如,在一个 Web 服务器上,多个用户访问同一个网站,服务器会并发地处理这些请求,同时响应每个请求,但是在某一时刻只有一个请求被处理;

并行:指多个任务同时在执行,并且它们真正地同时执行,通常需要多个 CPU 或者多台计算机协同工作。

例如,在一个分布式计算系统中,不同的计算节点可以同时执行不同的任务,并在完成任务后将结果汇总,以加速计算的过程。

接下来是同步和异步:

同步:指调用某个函数或方法时,程序必须等待函数或方法执行完毕才能继续往下执行。

最熟知的便是使用同步机制来控制多个线程之间的访问,如在 Java 中的 synchronized  关键字可以确保同一时间只有一个线程可以访问某个对象的临界区,避免了多个线程同时修改同一个对象导致的数据不一致问题;

异步:指调用某个函数或方法时,程序可以继续往下执行,不必等待函数或方法执行完毕。当函数或方法执行完毕后,程序会得到一个通知或回调来处理结果。在 Java 中可以使用 CompletableFuture 类来异步执行某个任务,从而提高程序的性能。

虽然并发和并行、同步和异步都是计算机领域中常用的概念,但是它们的区别还是很明显的。并发和并行关注的是任务的执行方式,同步和异步则关注的是数据的处理方式

前端

题目一

用 CSS 和 JS 来实现动画分别有哪些优缺点?

用 CSS 和 JS 来实现动画各有其优缺点,具体如下:

使用 CSS 实现动画的优缺点:

优点:

  • 硬件加速:CSS 动画会使用浏览器的 GPU 来进行硬件加速,能够更加流畅和高效地运行。
  • 简单易用:CSS 动画通常只需要几行代码就能实现基本的动画效果,不需要使用 JavaScript 来控制动画。
  • 低资源占用:CSS 动画通常比 JavaScript 动画使用更少的 CPU 和内存资源,因此更适合用于简单的动画效果。

缺点:

  • 限制较大:CSS 动画在实现复杂的动画效果时,受到限制较大,不能像 JavaScript 动画那样自由控制动画的速度、方向等。
  • 兼容性问题:由于不同浏览器对 CSS 动画支持程度不同,因此在实现时需要考虑浏览器兼容性问题。
  • 可维护性差:当动画效果较为复杂时,使用 CSS 实现的代码会变得冗长和难以维护,因此需要进行代码优化和结构设计。

使用 JavaScript 实现动画的优缺点:

优点:

  • 自由控制:JavaScript 动画能够更加自由地控制动画的速度、方向等,可以实现更加复杂的动画效果。
  • 兼容性好:由于 JavaScript 是浏览器通用的语言,因此在实现动画效果时,能够更好地兼容不同的浏览器。
  • 可维护性强:使用 JavaScript 实现动画时,代码结构更加灵活,能够更好地维护和扩展。

缺点:

  • 资源占用高:JavaScript 动画通常需要更多的 CPU 和内存资源,因此在实现动画效果时需要考虑系统资源的消耗问题。
  • 性能问题:JavaScript 动画性能受 JavaScript 引擎的影响,而不是浏览器引擎,因此需要对代码进行优化以提高动画性能。
  • 复杂度高:JavaScript 动画的实现复杂度通常比 CSS 动画高,因此需要对动画效果进行设计和规划。
题目二

JS 中怎么阻止事件冒泡和事件默认行为?

在 JavaScript 中,可以通过以下方式阻止事件的冒泡和默认行为:

阻止事件冒泡:事件冒泡是指当一个子元素触发了某个事件后,事件会一直冒泡到它的父元素,直到到达文档根节点。为了阻止事件冒泡,可以使用事件对象的 stopPropagation() 方法。例如:

document.getElementById("child").addEventListener("click", function(event) {
  // 阻止事件冒泡
  event.stopPropagation();
});

上面的代码中,当子元素被点击时,事件不会继续冒泡到父元素。

阻止事件默认行为:

事件的默认行为是指事件发生时,浏览器会默认执行的一些操作,例如提交表单、打开链接等。为了阻止事件的默认行为,可以使用事件对象的 preventDefault() 方法。例如:

document.getElementById("link").addEventListener("click", function(event) {
  // 阻止链接的默认跳转行为
  event.preventDefault();
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值