面试实题:No.18

1、项目中实际遇到的多线程业务有哪些?

     首先,基本上使用到多线程的地方都是数据量较多而单一执行影响效率故此采用的多线程。那么,根据这一场景我们项目中,文件的上传、图片的上传、单点登录、下单、加入购物车、支付……都是线程的实际应用场景。

     仅仅知道这些就够了吗?不够的,你还需要知道如何去创建线程、线程池以及线程的开辟数量等问题。因涉及内容较多大家不妨直接在我的博客中搜索查询。

2、项目中什么情况下会内存溢出,怎么解决的?

     首先,内存溢出指的是 应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存。

     产生原因:

  1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;

  2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;

  3.代码中存在死循环或循环产生过多重复的对象实体;

  4.使用的第三方软件中的BUG;

  5.启动参数内存值设定的过小。

   解决方案:

     第一步,就是修改JVM启动参数,直接增加内存;

     第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误;

     第三步,安排有经验的编程人员对代码进行走查和分析,找出可能发生内存溢出的位置;

     第四步,使用内存查看工具动态查看内存使用情况。

在讲解过程中最好能够结合到项目中,例如jvm参数是如何配置的,又是如何对业务代码进行调优的等,在此基础上也不妨具体讲解一下JVM和GC机制等。

3、项目中版本控制工具Git怎么使用的?

第一步,使用git init创建本地仓库,给我们创建一个工作区,在这里面进行代码创建修改;

第二步,使用git add新增文件,把文件保存在暂存区;

第三步,使用git commit提交到仓库;

第四步,使用git push把文件推送到服务器,这样就可以拖着小伙伴一起入坑进行开发了。

以上是使用的基本流程,而在应用过程中更多的是会出现提交冲突等问题,所以就此问题也不妨整理总结一下。

4、参与过项目测试吗?

     关于项目测试这一块大家多少都是会参与到的。最基本的而言单元测试总是做过的,而对于我们而言最好还是能够了解到完整的测试流程。

https://blog.csdn.net/A_BlackMoon/article/details/104916023

以上链接,对整个项目测试前期后期等均讲解的比较详细,可进行参考。

5、自己所做的项目有上线的吗?

     一个非常实际和大家普遍关注的问题。若是项目上线了最好附上对应的项目链接便于面试官查看,而有部分同学所做的是传统项目,例如OA办公管理项目只是针对于企业自己来用便不必附上链接了。而未上线,在面试官问及的时候能够将详细原因讲解清楚:已进入内侧环节,自己所负责的模块一完成;项目后期资金链断了导致项目无法如期进行等,大家可作为参考。

6、重写和重载的区别?

重写:当一个子类继承一父类,而子类中的方法与父类中的方法的名称,参数个数、类型都完全一致时,就称子类中的这个方法重写了父类中的方法。

重载:一个类中的方法与另一个方法同名,但是参数表不同,这种方法称之为重载方法。

实现方式:

重写:通常,派生类继承基类的方法。因此,在调用对象继承方法的时候,调用和执行的是基类的实现。但是,有时需要对派生类中的继承方法有不同的实现。例如,假设动物类存在“跑"的方法,从中派生出马和狗,马和狗的跑得形态是各不相同的,因此同样方法需要两种不同的实现,这就需要"重新编写"基类中的方法。"重写"基类方法就是修改它的实现或者说在派生类中重新编写。

重载:在一个类中用相同的名称但是不同的参数类型创建一个以上的过程、实例构造函数或属性。

7、Tomcat如何调优?

可以考虑从内存,并发,缓存,安全,网络,系统等进行入手。

并发优化、缓存优化、IO优化、开启线程池、添加listenter、组件优化等。

具体的优化参数配置,建议大家可以具体查一下。最好准备两个。

8、分页查询的关键字是?

MySQL:limit;

oracle:rownum;

1.oracle数据库分页

select * from (select a.*,rownum rc from 表名 where rownum<=endrow) a where a.rc>=startrow

oracle分页有通用写法,假设一页5行

select * from (    select t.*,rownum from (        select * from table1 where condition order by column) t )    where rownum>(pangeNow-1)*5 and rownum<=(pageNow)*5

2.DB2数据库分页

Select * from (select rownumber() over() as rc,a.* from (select * from 表名 order by 列名) as a) where rc between startrow and endrow

3.SQL Server 2000数据库分页

Select top pagesize * from 表名 where 列名 not  in(select top pagesize*page 列名 from  表名 order by 列名) order by 列名

4.SQL Server 2005数据库分页

Select * from (select 列名,row_number() over(order by  列名1) as 别名from 表名) as t where t.列名1>=startrow and t.列名1<=endrow

5.MySQL数据库分页

Select * from 表名 limit startrow,pagesize(Pagesize为每页显示的记录条数)

6.PostgreSQL数据库分页

Select * from 表名 limit pagesize,offset startrow(Pagesize为每页显示的记录条数.)

9、用过临时表吗?怎么用的?为什么用?

什么是临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。为什么会产生临时表:一般是由于复杂的SQL导致临时表被大量创建。

临时表分为两种,一种是内存临时表,一种是磁盘临时表。内存临时表采用的是memory存储引擎,磁盘临时表采用的是myisam存储引擎(磁盘临时表也可以使用innodb存储引擎,通过internal_tmp_disk_storage_engine参数来控制使用哪种存储引擎,从mysql5.7.6之后默认为innodb存储引擎,之前版本默认为myisam存储引擎)。分别通过Created_tmp_disk_tables 和 Created_tmp_tables 两个参数来查看产生了多少磁盘临时表和所有产生的临时表(内存和磁盘)。

内存临时表空间的大小由两个参数控制:tmp_table_size 和 max_heap_table_size 。一般来说是通过两个参数中较小的数来控制内存临时表空间的最大值,而对于开始在内存中创建的临时表,后来由于数据太大转移到磁盘上的临时表,只由max_heap_table_size参数控制。针对直接在磁盘上产生的临时表,没有大小控制。

下列操作会使用到临时表: 

1、union查询;

2、对于视图的操作,比如使用一些TEMPTABLE算法、union或aggregation;

3、子查询;

4、join 包括not in、exist等;

5、查询产生的派生表;

6、复杂的group by 和 order by;

7、Insert select 同一个表,mysql会产生一个临时表缓存select的行;

8、多个表更新;

9、GROUP_CONCAT() 或者 COUNT(DISTINCT) 语句;

Mysql还会阻止内存表空间的使用,直接使用磁盘临时表:

1、表中含有BLOB或者TEXT列;

2、使用union或者union all时,select子句有大于512字节的列;

3、Show columns或者 desc 表的时候,有LOB或者TEXT;

4、GROUP BY 或者 DISTINCT 子句中包含长度大于512字节的列。

10、数据库视图的优点?

比如一个比较复杂的查询不想每次都写很多语句,就可以写个视图。或者给特定用户开放某些表的读取权限,但要加一些行和列的限制,也可以写个视图。

第一点:使用视图,可以定制用户数据,聚焦特定的数据;

在实际过程中,公司有不同角色的工作人员,我们以销售公司为例的话, 采购人员,可以需要一些与其有关的数据,我们可以根据这一实际情况,专门为采购人员创建一个视 图,以后他在查询数据时,只需select * from view_caigou;

第二点:使用视图,可以简化数据操作;

我们在使用查询时,在很多时候我们要使用聚合函数,同时还要 显示其它字段的信息,可能还会需要关联到其它表,这时写的语句可能 会很长,如果这个动作频繁发生的话,我们可以创建视图,这以后,我 们只需要select * from view1就可以啦;

第三点:使用视图,基表中的数据就有了一定的安全性;

因为视图是虚拟的,物理上是不存在的,只是存储了数据的集合,我们可以 将基表中重要的字段信息,可以不通过视图给用户,视图是动态的数据的集 合,数据是随着基表的更新而更新。同时,用户对视图,不可以随意的更改 和删除,可以保证数据的安全性。

第四点:可以合并分离的数据,创建分区视图。

随着社会的发展,公司的业务量的不断的扩大,一个大公司,下属都设有很 多的分公司,为了管理方便,我们需要统一表的结构,定期查看各公司业务 情况,而分别看各个公司的数据很不方便,没有很好的可比性,如果将这些 数据合并为一个表格里,就方便多啦,这时我们就可以使用union关键字, 将各分公司的数据合并为一个视图。

这部分内容也可以在数据库优化的时候讲一下,估计是加分项,因为大多数同学只是在讲SQL语句 的优化。

11、drop、delete、trancate的区别?

1、在速度上,一般来说,drop> truncate > delete。

2、在使用drop和truncate时一定要注意,虽然可以恢复,但为了减少麻烦,还是要慎重。

3、如果想删除部分数据用delete,注意带上where子句,回滚段要足够大;

   如果想删除表,当然用drop; 

   如果想保留表而将所有数据删除,如果和事务无关,用truncate即可;

   如果和事务有关,或者想触发trigger,还是用delete;

   如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据。

这部分同样可以放到日常的SQL使用中进行讲解,且最好实际、详细的了解一下。

12、MySQL的外连接用过吗?如何使用?

左外连接(LEFT JOIN)是指将左表中的所有数据分别与右表中的每条数据进行连接组合,返回的除内连接外,还包括左表中不符合条件的数据,并在右表的相应列中添加NULL值。

简单点来说,就是可以等值连接的就等值连接,不能的左表数据保留,右表数据全部用NULL填上。

select  * from b left join a on a.bno=b.bno where a.bno IS NULL;

右外连接(RIGHT JOIN)是指右表中的所有数据分别与左表中的每条数据进行连接组合,返回的结构除内连接数据外,还包括右表中不复合条件的数据,并在左表的相应列中添加NULL。

select * from a right join b on a.bno=b.bno;

全外连接(FULL  JOIN 或 FULL OUTER JOIN) 完整外部连接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。

总结:如果要确保在连接的过程中数据不会丢失,我们就需要使用外连接,但是我们也需要知道哪个表的信息是将会被丢失的。这里有个简单点的方法,就是左外和右外各写一句。但是表的位置要相同(均为b在前或者均为a在前,如下),这样观察一下两表的不同就知道了。

select * from b left join a on a.bno=b.bno;

select * from b right join a on a.bno=b.bno;

13、char和varchar的区别?

char和varchar类型声明长度表示用户想保存的最大字符数,其中char(M)定义的列的长度为固定的,M的取值可以0-255之间,当保存char值时,在它们的右边填充空格以达到指定的长度。当检索到char值时,尾部的空格被删除掉(如下图)。在存储或检索过程中不进行大小写转换。char存储定长数据很方便,char字段上的索引效率很高。

varchar(M)定义的列的长度是可变长度字符串,在MySQL5.0以上的版本中,varchar的数据类型长度支持到了65535,因为起始位和结束位占去了3个字节,所以其整体最大长度为65532字节(varchar的最大有效长度由最大行大小和使用的字符集确定)。

除此之外,与char比,varchar值保存时只保存需要的字符数,另加一个字节来记录长度(长度超过255时需要2个字节)。

同样在char和varchar尾部加空格,检索时char类型后的被删掉,而varchar类型的保存。

应用场景:

1、对于MyISAM表,尽量使用Char,对于那些经常需要修改而容易形成碎片的myisam和isam数据表就更是如此,它的缺点就是占用磁盘空间;

2、对于InnoDB表,因为它的数据行内部存储格式对固定长度的数据行和可变长度的数据行不加区分(所有数据行共用一个表头部分,这个标头部分存放着指向各有关数据列的指针),所以使用char类型不见得会比使用varchar类型好。事实上,因为char类型通常要比varchar类型占用更多的空间,所以从减少空间占用量和减少磁盘i/o的角度,使用varchar类型反而更有利;

3、存储很短的信息,比如门牌号码101,201……这样很短的信息应该用char,因为varchar还要占个byte用于存储信息长度,本来打算节约存储的现在得不偿失。

4、固定长度的。比如使用uuid作为主键,那用char应该更合适。因为他固定长度,varchar动态根据长度的特性就消失了,而且还要占个长度信息。

5、十分频繁改变的column。因为varchar每次存储都要有额外的计算,得到长度等工作,如果一个非常频繁改变的,那就要有很多的精力用于计算,而这些对于char来说是不需要的。

14、springboot和spring的区别?

     maven依赖: Spring Boot只需要一个依赖项来启动和运行Web应用程序, 在构建期间,所有其他依赖项将自动添加到最终归档中。

     常用依赖项: spring-boot-starter-data-jpa、 spring-boot-starter-security、 spring-boot-starter-test、 spring-boot-starter-web、 spring-boot-starter-thymeleaf等。

     MVC配置: Spring配置都是通过一个名为auto-configuration的进程添加Boot web starter来自动包含的; Spring Boot将自动扫描应用程序中存在的依赖项,属性和bean,并根据这些内容启用相应的配置。

     模板引擎配置: Spring中,我们需要为视图解析器添加 thymeleaf-spring5依赖项和一些配置; Spring Boot 只需要spring-boot-starter-thymeleaf的依赖项 来启用Web应用程序中的Thymeleaf支持。 一旦依赖关系添加成功后,我们就可以将模板添加到src / main / resources / templates文件夹中,Spring Boot将自动显示它们。

     安全配置: Spring需要标准的 spring-security-web和spring-security-config 依赖项来在应用程序中设置Security。 我们需要添加一个扩展WebSecurityConfigurerAdapter的类,并使用@EnableWebSecurity注解; Spring Boot也需要这些依赖项才能使其工作。但是我们只需要定义spring-boot-starter-security的依赖关系,它会自动将所有相关的依赖项添加到类路径中。

     应用引导Application Bootstrap。

     打包和部署: Spring Boot Maven插件在Maven中提供Spring Boot支持。它还允许打包可执行jar或war档案并“就地”运行应用程序。与spring相比,在部署环境中Spring Boot的一些优点包括

  1. 提供嵌入式容器支持;

  2. 使用命令java -jar独立运行jar;

  3. 在外部容器中部署时,可以选择排除依赖关系以避免潜在的jar冲突;

  4. 部署时灵活指定配置文件的选项;

  5. 用于集成测试的随机端口生成。

综上所述:Spring Boot只是Spring本身的扩展,使开发,测试和部署更加方便。

15、怎么搭建一个springboot项目?

1.首先新建一个web项目;

2.修改pom.xml配置文件,引入SpringBoot的核心依赖;

3.新建一个启动类;

4.在resources目录下新建一个application.yml或application.properties配置文件。

16、springboot的启动类加什么注解?

@ComponentScan这个注解在Spring中很重要,它对应XML配置中的元素,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。

@EnableAutoConfiguration 简单概括一下就是,借助@Import的支持,收集和注册特定场景相关的bean定义。

@SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。

@Inherited作用是,使用此注解声明出来的自定义注解,在使用此自定义注解时,如果注解在类上面时,子类会自动继承此注解,否则的话,子类不会继承此注解。

@Documented注解表明这个注释是由 javadoc记录的,在默认情况下也有类似的记录工具。 如果一个类型声明被注释了文档化,它的注释成为公共API的一部分。

17、springAOP的应用场景?

应用场景:

Authentication 权限

Caching 缓存

Context passing 内容传递

Error handling 错误处理

Lazy loading 懒加载

Debugging  调试

logging, tracing, profiling and monitoring 记录跟踪 优化 校准

Performance optimization 性能优化

Persistence  持久化

Resource pooling 资源池

Synchronization 同步

Transactions 事务

如何使用AOP:

可以通过配置文件或者编程的方式来使用Spring AOP。

配置可以通过xml文件来进行,大概有四种方式:

1.        配置ProxyFactoryBean,显式地设置advisors, advice, target等;

2.        配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象;

3.        通过<aop:config>来配置;

4.        通过<aop: aspectj-autoproxy>来配置,使用AspectJ的注解来标识通知及切入点。

也可以直接使用ProxyFactory来以编程的方式使用Spring AOP,通过Proxy。

18、mybatis模糊查询怎么写?

1.使用concat (oracle不支持三个参数的写法,mysql支持):  ... FIELD_NAME like concat(concat('%',#{fieldName}),'%')  ;

2.使用’%'与||:  ...FIELD_NAME like'%'||#{fieldName}||'%'  ;

3.使用’%'与||:...FIELD_NAME like'%'||trim(#{fieldName})||'%'  ;

4.使用$:...FIELD_NAME like'%${fieldName}'%' .

MySQL:...FIELD_NAME like CONCAT('%',#{fieldName},'%');

SqlServer:...FIELD_NAME like '%'+#{fieldName}+'%'.

19、mybatis如何写分页?

数组分页、SQL分页、拦截器分页、RowBounds分页。一般咱们常用的是SQL分页:select * from student limit #{currIndex} , #{pageSize};

20、base64加密算法的原理?

它是用64个可打印字符表示二进制所有数据方法。由于2的6次方等于64,所以可以用每6个位元为一个单元,对应某个可打印字符。我们知道三个字节有24个位元,就可以刚好对应于4个Base64单元,即3个字节需要用4个Base64的可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中一般有所不同。但是,我们经常所说的Base64另外2个字符是:“+/”。

转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的bit用0补足。 然后,每次取出6个bit,按照其值选择

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。

如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

编码后的数据比原始数据略长,为原来的4/3。无论什么样的字符都会全部被编码,因此不像Quoted-printable 编码,还保留部分可打印字符。所以,它的可读性不如Quoted-printable编码!

21、你知道哪些加密算法?

MD5加密算法、 DES加密算法、 RSA加密算法、 IDEA加密算法、 DSA加密算法、 AES加密算法、 Elgamal、 Base64加密算法、 SHA1加密算法、 PKCS加密算法等。

在回答此问题的时候最好能够就某几种算法做详细的解释。

22、HashMap的底层原理?

HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。

23、SQL语句的优化?

SQL语句优化:索引、where、having、like、in、not in、临时表等;

数据库表结构优化:分库分表、表空间分配、表结构优化等。

在讲述过程中距离SQL语句进行比较以及设计表结构的思路和背景原因,这样比较好。

https://blog.csdn.net/A_BlackMoon/article/details/104924120

24、socket协议?

socket通信其实是有两种方式:TCP和UDP过程。

TCP是可靠地面向连接的通信过程,含有三次握手四次挥手的机制。

UDP是不可靠的无连接的通信过程,客户端只管发,不管服务端有没有接受到。

从上图我们可以看到,Socket实现的步骤大体包含以下几个步骤:

(1)创建Server和client的ServerSocket和Socket。

(2)打开链接到Socket的输入输出流

(3)按照协议对Socket进行读取操作

(4)关闭输入输出流、关闭Socket。

1、基于TCP的socket通信

我们拿男孩做客户端,女孩因为有很多人追求,所以做服务端,一个服务端可被多个男孩客户端请求表白。我们这里先看女孩服务端的具体步骤:

(1)创建ServerSocket对象,绑定监听端口。

(2)通过accept()方法监听客户端请求

(3)连接建立后,通过输入流读取客户端的数据

(4)通过输出流,向客户端回应信息

具体的步骤已经很清晰了,我们再来看看男孩客户端的步骤:

(1)创建Socket并指定端口

(2)通过输出流向服务端发送一个请求

(3)等待服务端的回应 获取输入流,读取客户端信息(将字节流转化为字符流),并保存在缓冲区中

(4)关闭资源

2、基于UDP的Socket通信

UDP的通信模式其实是无连接的不可靠的通信协议,举个例子,花心男孩向女孩表白,就给女孩写了一封情书,然后不管女孩有没有收到情书,自己继续向其他女孩表白。我们这里还是以女孩为服务端。

接收客户端发送的数据

(1)创建服务器端DatagramSocket指定端口

(2)创建数据报DatagramPacket,接收客户端发送的数据

(3)接收客户端发送的数据

(4)读取数据

向客户端响应数据

(1)定义客户端的地址、端口号、数据

(2)创建数据报,包含响应的数据信息

(3)响应客户端

(4)关闭资源

---------------

然后再来看一下客户端的请求:

向服务器端发送数据

(1)定义服务器的地址、端口号、数据

(2)创建数据报,包含发送的数据信息

(3)创建DatagramSocket对象

(4)向服务器端发送数据报

接收服务器端响应的数据

(1)创建数据报DatagramPacket,用于接收服务器端响应的数据

(2)接收服务器响应的数据

(3)读取数据

(4)关闭资源

25、会不会oracle数据库?

若是会直接进行讲解即可,在项目中那块应用过怎么使用的。若是没有应用过可以讲解对其了解过,然后将其与MySQL进行比较进行简单阐述。

发布了441 篇原创文章 · 获赞 1021 · 访问量 53万+

猜你喜欢

转载自blog.csdn.net/A_BlackMoon/article/details/104924820