您的位置:首页 > 编程语言 > Java开发

Java Case Interview two

2021-05-05 20:26 155 查看

并发相关知识点

参见博客

为什么使用线程池?线程池有哪些参数?

  1. 降低资源消耗
  2. 提高响应速度
  3. 提高线程的可管理性

corePoolSize 核心线程数 正常工作创建的线程数
maxinumPoolSize 最大线程数 表示最大允许被创建的线程。
keepAliveTime、unit 存活时间 心线程数之外的线程的空间存活时间。

workQueue 工作队列 用来存放待执行的任务
THreadFactory 线程工厂用来产生线程执行任务(可以使用默认的具有相同的优先级,且均不是守护线程也可以自定义)
handler 拒绝策略 当线程池关闭或者无法执行新的线程(最大线程数和队列都已满)

线程池执行流程

  1. 判断核心线程是否都被占用
  2. 判断任务队列是否已满
  3. 是否达到最大线程数
  4. 拒绝策略

线程池中阻塞队列的作用?为什么先添加到工作队列,而不是创建最大线程?

作用

  1. 一般队列当任务数超出缓冲长度时,就无法保留,阻塞队列可以通过阻塞保留住当前 想要继续入队的任务。
  2. 没有任务时,可以阻塞获取任务的线程,使线程进入wait状态,释放CPU资源。
  3. 阻塞队列自带阻塞和唤醒功能

原因

  1. 在创建新线程的时候,要获取全局锁, 这个时候其他的就要阻塞,影像了整体的效率。

线程复用

线程池中每次执行任务不是调用Thread.start()方法,而是让线程执行一个循环任务,
在这个循环任务中不停的检查是否有任务需要执行,如果有调用线程的run()执行。

BeanFactory 和 ApplicationContext 有什么区别

  • ApplicatioinContext是BeanFactory子接口;

  • ApplicationContext扩展了BeanFactory:

      继承MessageSource,支持国际化信息
    1. 继承ResourcePatternResolver,统一的资源文件访问方式
    2. 继承ApplicationEventPublisher,提供监听器中注册bean时间
    3. 同时加载多个配置文件;载入多个上下文,使得每一个上下文都专注于一个特定的层次。比如web层。
  • BeanFactory 采用的懒加载模式

  • ApplicationContext 在容器启动时一次创建所有的bean

  • BeanFactory只能编程式创建,而ApplicationContext还能声明式创建,如使用ContextLoader

  • BeanFactory 和 ApplicationContext 都支持BeanPostProcessor, BeanFactoryPostProcessor的使用,
    但是BeanFactory需要手动注册,而ApplicationContext则是自动注册

SpringBean 生命周期

  1. 实例化
  2. 设置属性autoware注入
  3. 设置实现Aware接口相关的属性
  4. 调用BeanPostProcessor的postProcessBeforeInitialization方法
    (包括 BeanPostProcessor的 初始化前或者后方法 和 InitializingBean的 afterPropertiesSet方法)
  5. 调用容器中该bean指定的init方法
  6. 调用BeanPostProcessor的postProcessAfterInitialization方法
  7. 使用bean
  8. 调用DisposableBean 的 destroy()方法

引用月染霜华博客

Spring中Bean支持的几种作用域

sigleton 默认,每一个容器只有一个Bean实例,单例模式由BeanFactory自身来维护。
prototype 为每一个bean请求提供一个实例,每次注入式都会创建一个新对象
request bean被定义为在每个HTTP请求中创建一个单例对象
session 确保每个session中有一个bean实例
application bean被定义为在ServletContext的生命周期中复用的一个单例对象
websocket bean被定义为在websocket生命周期中复用一个单例独享

global-session:全局作用

事务传播机制

REQUIRED 默认的事务传播类型,如果有事务则加入;没有则新建一个事务
SUPPORTS 如果有事务则加入;如果没有则以非事务方式执行
MANDATORY 当前存在事务,则加入事务;没有则抛出异常
REQUEST_NEW 有则挂起该事务;没有则创建一个事务;
NOT_SUPPORTED 有则挂起该事务;没有则以非事务方式执行
NERVER 不使用事务,如果存在事务则抛出异常
NESTED 有则嵌套事务中执行;否则开启一个事务

Note

  • REQUEST_NEW 是开启一个事务,并且新开启的事务与事务无关
  • NESTED 开启一个嵌套事务,父事务回滚,子事务必回滚;反之,
    子事务回滚,父事务不一定回滚,可以catch吃掉异常。
  • REQUIRED 要求调用方和被调用方使用同一事务

事务的基本特性和隔离级别

事务的基本特性ACID

atomiticy 一个事务中的操作要么全部失败,要么全部成功
consistency 在一个系统中,整体的资源保持最终一致
isolation 隔离性 指事务在提交前不可被其他事务读到
durability 事务提交后,所做的修改就会永久的保存到数据库中

隔离级别

Read Uncommit 未提交读,读到未提交的数据 脏读
Read Commit 提交读,读到提交后的数据 不可重复读(lock in share mode 共享锁来避免) Oracle默认级别
Read Repeatable 可重复读 每次读到的结果一样,一个事务开始读到就认定这个值,不管其他事务有没有该这条数据
但是如果是范围查询,可能查到的结果会变,这就造成幻读(加间隙锁避免)
serializable 串行,一般不会使用,会给每一行读到的数据加锁,影响并发

spring 事务什么时候失效

  1. 发生自调用,处理办法,不要自调用,使用注入对象调用
  2. @Transactional
    修饰的方法不是public修饰符,如果要在非public上实现事务
    可以使用AspectJ代理模式
  3. 数据库不支持事务
  4. 要开启事务方法的类未交给容器管理
  5. 异常被吃掉,事务不会回滚

Spring Boot、Spring MVC 和 Spring 有什么区别

Spring 是一个 IOC 容器用来管理Bean,使用依赖注入和控制反转,可以很方便的整合各种框架;
提供了AOP特性可以对日志,事务等功能从业务代码中剥离出来,集中管理。

Spring MVC 是 Spring 对Web框架的一个解决方案,提供了前段控制器Servlet,用来接收请求,
然后定义了一套路由策略(url->handler)以及适配执行hanle,将handle结果使用视图解析计数生
成视图展示给前端。

Spring Boot 是Spring提供的一个快速开发工具,让程序员快速使用Spring+Spring MVC。简化配置
(约定了默认配置),整合了一系列解决方案(Starter机制)、Redis、MongoDB、elasticsearch

Spring MVC工作流程

  1. 用户请求发往前端控制器 DispatcherServlet
  2. DispatcherServlet 调用处理器映射器 RequestMapping
  3. 处理映射器找到具体的处理器,和相关的拦截器组合成一个 HandlerExecutionChain
  4. DispatcherServlet 获取处理器适配器,并调用处理器适配器的 handle() 方法
    并且返回ModelAndView给 DispatcherServlet
  5. DispatcherServlet 将 ModelAndView 传给视图解析器 ViewResolver 进行解析
  6. 执行拦截器进行一些处理
  7. DispatcherServlet 返回 processedRequest, response, mappedHandler, mv, dispatchException

DispatcherServlet 中的方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

try {
ModelAndView mv = null;
Exception dispatchException = null;

try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}

// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

if (asyncManager.isConcurrentHandlingStarted()) {
return;
}

applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

Spring Boot 自动配置原理

@improt
处理文件包路径
SPI
SpringFactoriesLoader.loaderFactoryNames() 方法加载在 META-INF/spring.factories下配置的类
,PS:在此文件中添加jar包中相应的类,可以注入jar包中的类到容器中
@Configuration
指定该类为配置类
@Bean
在配置类中指定需要配置的类,并加载到容器中,比如redis,kafka配置类

MySQL 聚族索引和非聚族索引的区别

聚族索引 将数据和索引放到一块,并且按照一定的顺序排列
非聚族索引 叶子节点不放数据,存储数据的地址值


索引数据结构 B+ Tree Hash Index

MySql Select 时索引type

  • const 通过索引一次命中,匹配一行数据
  • system 表中只有一行数据,相当于系统表
  • eq_ref 唯一性索引扫描,对于每个索引建,表中只有一条记录与之匹配
  • ref 非唯一性索引扫描,返回匹配的某个值的所有
  • range 只检索给定范围的行,使用一个索引来选择航 一般用于betweeen < >
  • inedex 只遍历索引树
  • all 全表扫描

MySQL 数据库锁

  • 共享锁 读锁

  • 排它锁 写锁

  • 表锁 锁力度大 并发不好

  • 行锁 锁力度大小 并发好 会出现死锁

  • 记录锁

    只锁表中的一行,精确条件命中,并且命中条件字段是唯一索引 可以避免重复度 脏读问题
  • 页锁 会出现死锁

  • 间隙锁 锁住表记录的某一个区间,左开右闭

  • 临建锁 锁住表记录的某一个区间,左闭右闭

  • 意向共享锁 当一个事务视图对整个表加共享锁之前,首先获得这个表的意向共享锁

  • 意向排它锁 当一个事务视图对整个表加排他锁之前,首先获得这个表的意向排他锁

  • InnoDB 默认 行锁
    MyISAM 默认 表锁

    参考资料

    1. B站视频地址
    2. JDK 8 源码
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: