信也科技一面凉经

1.在项目经历里挑一个详细介绍一下 项目的应用场景 

2.项目里用到多线程是怎么用的?回答:线程池 

用通过 ThreadPoolExecutor 构造函数的方式创建的线程池

3.线程池有哪些重要参数?回答:核心线程数、最大线程数、阻塞队列类型、抛出策略还有线程池类型。

线程池的核心线程数、最大线程数,当线程数大于核心线程数时多余的线程存活的时间,任务队列,拒绝策略。

4.线程池类型有哪些?回答:有固定一个线程的还有按照参数指定线程数的,还有按时执行任务的。

基于ThreadPoolExecutor共有四种类型线程池

FixedThreadPool:固定数量线程池

SingleThreadExecutor:单线程线程池

CachedThreadPool:缓存线程池(是一种大小可变的线程池,线程数量根据任务的数量自动调整。)

ScheduledThreadPoolExecutor:调度线程池(周期性地执行任务,或者在指定的时间执行任务。)

一般不建议采用Excutors类创建上述线程池,而是建议大家使用构造函数去创建线程池,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险

(1)FixedThreadPoolSingleThreadExecutor:使用的是无界阻塞队列,任务队列最大长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。

(2)CachedThreadPool:使用的是同步队列,允许创建的线程数量为 Integer.MAX_VALUE ,如果任务数量过多且执行速度较慢,可能会创建大量的线程,从而导致 OOM。

(3)ScheduledThreadPoolSingleThreadScheduledExecutor : 使用的无界的延迟阻塞队列DelayedWorkQueue,任务队列最大长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致 OOM。

  • 容量为 Integer.MAX_VALUELinkedBlockingQueue(无界队列):FixedThreadPoolSingleThreadExector 。由于队列永远不会被放满,因此FixedThreadPool最多只能创建核心线程数的线程。
  • SynchronousQueue(同步队列):CachedThreadPoolSynchronousQueue 没有容量,不存储元素,目的是保证对于提交的任务,如果有空闲线程,则使用空闲线程来处理;否则新建一个线程来处理任务。也就是说,CachedThreadPool 的最大线程数是 Integer.MAX_VALUE ,可以理解为线程数是可以无限扩展的,可能会创建大量线程,从而导致 OOM。
  • DelayedWorkQueue(延迟阻塞队列):ScheduledThreadPoolSingleThreadScheduledExecutorDelayedWorkQueue 的内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构,可以保证每次出队的任务都是当前队列中执行时间最靠前的。DelayedWorkQueue 添加元素满了之后会自动扩容原来容量的 1/2,即永远不会阻塞,最大扩容可达 Integer.MAX_VALUE,所以最多只能创建核心线程数的线程。

5.实际工作中参数怎么选择呢?比如核心线程数?回答:核心线程数和cpu个数有关,一般是2n+1个

这是固定的?不是固定的,要看任务是主要使用cpu的还是占用cpu比较少的。

如果我们设置的线程池数量太小的话,如果同一时间有大量任务/请求需要处理,可能会导致大量的请求/任务在任务队列中排队等待执行,甚至会出现任务队列满了之后任务/请求无法处理的情况,或者大量任务堆积在任务队列导致 OOM。这样很明显是有问题的,CPU 根本没有得到充分利用。

如果我们设置线程数量太大,大量线程可能会同时在争取 CPU 资源,这样会导致大量的上下文切换,从而增加线程的执行时间,影响了整体执行效率。

假设机器有N个CPU,那么对于计算密集型的任务(压缩、解压缩、加密、解密、科学计算等),应该设置线程数为N+1;对于IO密集型的任务(MySQL 数据库、文件的读写、网络通信),应该设置线程数为2N;对于同时有计算工作和IO工作的任务,应该考虑使用两个线程池,一个处理计算任务,一个处理IO任务,分别对两个线程池按照计算密集型和IO密集型来设置线程数。

最佳线程数 = N(CPU 核心数)∗(1+WT(线程等待时间)/ST(线程计算时间)),其中 WT(线程等待时间)=线程运行总时间 - ST(线程计算时间),WT/ST可以通过VisualVM 来查看。

综合来看,我们可以根据自己的业务场景,从“N+1”和“2N”两个公式中选出一个适合的,计算出一个大概的线程数量,之后通过实际压测,逐渐往“增大线程数量”和“减小线程数量”这两个方向调整,然后观察整体的处理时间变化,最终确定一个具体的线程数量。

6.多线程会带来一些并发问题,一般用锁来处理。乐观锁和悲观锁你了解吗都是什么概念?应用于什么场景

悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。常见的悲观锁有java的synchronized、ReentrantLock等独占锁。悲观锁通常用于写比较多的情况,可以避免频繁失败和重试影响性能,开销是固定的。

乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。JUC包下的原子变量类,比如AtomicInteger、LongAdder就是使用了乐观锁的一种实现方式CAS实现的。乐观锁通常用于写比较少的情况,比如多读场景,竞争比较少,可以避免频繁加锁影响性能。不过乐观锁主要针对的对象是单个共享变量。

从 JDK 1.5 开始,提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量来操作。

7.你用过的锁有哪些,sychronized锁升级的流程

8.看你的简历有一个oom的排查和一个循环依赖的排查,能详细讲讲吗(这里讲的不好,再深入一下)

日志显示OOM,是一个堆内存的泄漏 OutOfMemoryError: Java heap space

查看dump文件,默认存储在启动该jar的用户根目录下,用MemoryAnalyzer对dump文件进行分析,发现占用内存异常的是一个map,定位到DistributedFileSystem,以此为关键字在项目里排查。

定位到代码中发现是之前为解决“两个HDFS集群namespace同名时会造成两个集群读取到同一套文件系统”的问题,由调用get(hadoopConfig)方法换为调用newInstance方法新建实例。但是该方法中会一直往一个静态的cache的map里放值,在定时多次调用的情况下,map一直不会被回收但是内部一直在添加新值造成OOM。后续解决方法是将FileSystem保存到map缓存里,FileSystem是通过集群名和集群配置生成的,如果map缓存中存在该实例就从缓存中读取,不存在才新增。

FileSystem是根据集群名和配置生成的,之前的get方法只用配置拿,因此同名的集群区分不了。

9.你项目哪里用到了redis 怎么用的(这里因为没问过也没深入下去,接下来把redis加入到项目里)

10.项目主要用mysql,处理过海量数据吗 有哪些优化手段?一般对哪些字段建索引,索引的个数为什么不是越多越好?

哪些情况需要创建索引:(1)主键会自动建立唯一索引 (2)频繁作为查询条件的字段需要建立索引,在where语句用到的字段加索引 (3)查询与其他表关联的字段,会在on的外键关系上建立索引 (4)多字段查询可以创建组合索引 (5)有序字段适合创建索引 (6)查询中统计或者分组字段(有区分度的字段,可能会拿来做分组的字段)

不适合加索引的地方:(1)频繁更新的字段不适合创建索引。更新字段的过程中,需要维护B+树结构,会频繁更新索引文件,降低SQL性能。(2)过长的字段不适合创建索引。(占用空间多)(3)无序的字段不适合创建索引。

优先使用联合索引,联合索引时将高区分度的字段放到前面。

创建过多的索引,会占用更多存储空间,另外也会严重影响SQL性能,每次更删改查SQL都需要更新大量索引文件。

11.看简历写到过设计模式,你熟悉哪些设计模式? 回答了建造者、简单工厂。

了解代理模式吗?哪里用过代理模式

12.hashmap结构

13.怎么判断能获取到的mysql锁是表级锁还是行级锁?

14.平时使用update select这些语句什么情况下会上锁,会上哪种锁

一些非技术相关提问:

1.过去开发时候 产品 测试 前端这些都有吧 介绍一下大概多少人 都有哪些角色参与生产

提问:组里的人员构成和架构?组里主要做什么 信贷平台的底层平台 做一些支付或者用户权限的认证 十个人 每两三个一组。初中高级比例大概怎么样?一比一

2.如果已经开发要完成了,产品提出加需求怎么办

3.今天面试我很多地方深入的了解都不够,你比较看中求职者哪些方面技术能力。比如redis这种我没有实际没有应用的,但是自己也看了一下,但没有实际经验面试官也不接着问下去了,比如这种知识我怎么准备呢

这还是每个面试官有不同的侧重点,从我的角度我更看重对你用过的技术的考察,如果工作三到四年没用过redis就不正常,但是你经验一年可以理解,但是目前大多数面试的十个人里面只有一两个没用过,所以还是建议多一些实际使用的经验。

总结:

1.多线程、mysql调优这些用过的但是不深入的东西需要重点学习!

2.redis看完基础教程以后加入到项目里,不要让他成为短板。

3.OOM和循环依赖那个的介绍要再熟悉深入一下。

4.leetcode还是要继续刷。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/40435.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【爱书不爱输的程序猿】公网访问本地搭建的WEB服务器之详细教程

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本地电脑搭建Web服务器并用cpolar发布至公网访问 前言1. 首先将PHPStudy、WordPress、cpolar下载到电脑2. 安装PHPStudy3. 安装cpolar,进入Web-UI界面4.安装wordpress5.…

KU Leuven TU Berlin 推出“RobBERT”,一款荷兰索塔 BERT

荷兰语是大约24万人的第一语言,也是近5万人的第二语言,是继英语和德语之后第三大日耳曼语言。来自比利时鲁汶大学和柏林工业大学的一组研究人员最近推出了基于荷兰RoBERTa的语言模型RobBERT。 谷歌的BERT(来自Transformers的B idirectional …

C语言 常用工具型API --------system()

函数名: system() 用 法: int system(char *command); 原理: 创建一个子进程去加载一个新程序执行,而Linux命令基本都是一个单独的进程实现的,所以你所掌握的Linux命令越多,该函数…

AUTOSAR规范与ECU软件开发(实践篇)4.2 基于Matlab/Simulink的软件组件开发

目录 前言 1 、Matlab/Simulink与AUTOSAR基本概念的对应关系 2 、软件组件内部行为建模方法

由浅入深学习Tapable

文章目录 由浅入深学习TapableTapable是什么Tapable的Hook分类同步和异步的 使用Sync*同步类型钩子基本使用bailLoopWaterfall Async*异步类型钩子ParallelSeries 由浅入深学习Tapable webpack有两个非常重要的类:Compiler和Compilation。他们通过注入插件的方式&a…

CentOS系统环境搭建(一)——Centos7更新

Centos7更新 更新 yum(包括centos内核) yum update执行后,系统将更新到centos 7.9。 从这一篇文章开始开始,我将开始在centos系统环境搭建🔗https://blog.csdn.net/weixin_43982359/category_12411496.html中开始对C…

【数据分析入门】Numpy进阶

目录 一、数据重塑1.1 透视1.2 透视表1.3 堆栈/反堆栈1.3 融合 二、迭代三、高级索引3.1 基础选择3.2 通过isin选择3.3 通过Where选择3.4 通过Query选择3.5 设置/取消索引3.6 重置索引3.6.1 前向填充3.6.2 后向填充 3.7 多重索引 四、重复数据五、数据分组5.1 聚合5.2 转换 六、…

回溯算法详解

目录 回溯算法详解 回溯VS递归 回溯算法的实现过程 n个结点构造多本节要讨论的是当给定 n(n>0)个结点时,可以构建多少种形态不同的树。 回溯算法详解 回溯算法,又称为“试探法”。解决问题时,每进行一步&#…

主成分分析Python代码

对于主成分分析详细的介绍:主成分分析(PCA)原理详解https://blog.csdn.net/zhongkelee/article/details/44064401 import numpy as np import pandas as pd标准PCA算法 def standeredPCA(data,N): #data:…

【golang】链表(List)

List实现了一个双向链表,而Element则代表了链表中元素的结构。 可以把自己生成的Element类型值传给链表吗? 首先来看List的四种方法。 MoveBefore方法和MoveAfter方法,它们分别用于把给定的元素移动到另一个元素的前面和后面。 MoveToFro…

十种排序算法(附动图)

排序算法 一、基本介绍 ​ 排序算法比较基础,但是设计到很多计算机科学的想法,如下: ​ 1、比较和非比较的策略 ​ 2、迭代和递归的实现 ​ 3、分而治之思想 ​ 4、最佳、最差、平均情况时间复杂度分析 ​ 5、随机算法 二、排序算法的分类 …

RabbitMq-1基础概念

RabbitMq-----分布式中的一种通信手段 1. MQ的基本概念(message queue,消息队列) mq:消息队列,存储消息的中间件 分布式系统通信的两种方式:直接远程调用,借助第三方完成间接通信 消息的发送方是生产者&#xff0c…

面试热题(二叉树的锯齿形层次遍历)

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行) 输入:root [3,9,20,null,null,15,7] 输出:[[3…

MySQL数据库-字符串函数详解

前言 MySQL数据库提供了多种不同类型的函数,用于处理字符串、日期、数值等数据类型,以及实现条件、聚合等操作,下面我们主要介绍字符串函数 CONCAT() 函数 CONCAT() 可用于将多个字符串连接在一起。 示例: SELECT CONCAT(Hell…

C++ STL stack queue

目录 一.stack 介绍 二.stack 使用 三.stack 模拟实现 普通版本: 适配器版本: 四.queue的介绍 五. queue使用 六.queue模拟实现 七.deque介绍 1.容器适配器 2.deque的简单介绍 3.deque的缺陷 4.为什么选择deque作为stack和queue的底层默认容…

System.Text.Encoding不同字符编码之间进行转换

System.Text.Encoding 是 C# 中用于处理字符编码和字符串与字节之间转换的类。它提供了各种静态方法和属性,用于在不同字符编码之间进行转换,以及将字符串转换为字节数组或反之。 在处理多语言文本、文件、网络通信以及其他字符数据的场景中&#xff0c…

Spring Boot 获取前端参数

Spring Boot 获取前端参数 在开发 Web 应用程序时,前端参数是非常重要的。Spring Boot 提供了多种方法来获取前端参数,本文将介绍其中的一些常用方法。 1. 使用 RequestParam 注解 RequestParam 注解是 Spring MVC 提供的一种常用方式,用于…

C++ 函数

函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的,但在逻辑上,划分通常…

pycharm调整最大堆发挥最大

python程序运行时,怎么提高效率,设置pycharm最大堆过程如下; 一、进入设置pycharm最大堆; 二、进入设置pycharm最大堆; 如果8g设置为6g左右,占75%左右最佳

5个实用的 Vue 技巧

在这篇文章中,我们将探讨五个实用的 Vue 技巧,这些技巧可以使你日常使用 Vue 编程更高效、更富有成效。无论你是Vue的初学者还是经验丰富的开发者,这些技巧都能帮助你编写更清晰、更简洁、更有效的代码。那么,让我们开始吧。 1. …