面试记录
一、多线程是什么
进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元;
线程:就是进程中的一个独立控制单元,线程在控制着进程的执行。一个进程中至少有一个进程。
多线程:一个进程中不只有一个线程。
二、为什么要用多线程
①、为了更好的利用cpu的资源;
②、进程之间不能共享数据,线程可以;
③、系统创建进程需要为该进程重新分配系统资源,创建线程代价比较小;
④、Java语言内置了多线程功能支持,简化了java多线程编程。
三、线程的生命周期:
- 新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;
- 就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;
- 运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。
- 等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。
- 终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。
四、创建线程的方法
1、继承Thread类:
步骤:①、定义类继承Thread;
2、实现Runnable接口: 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参方法。
实现步骤: ①、定义类实现Runnable接口
②、覆盖Runnable接口中的run方法
将线程要运行的代码放在该run方法中。
③、通过Thread类建立线程对象。
④、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程执行指定对象的run方法就要先明确run方法所属对象
⑤、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
3、通过Callable和Future创建线程:
实现步骤:①、创建Callable接口的实现类,并实现call()方法,改方法将作为线程执行体,且具有返回值。
②、创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值
③、使用FutureTask对象作为Thread对象启动新线程。
④、调用FutureTask对象的get()方法获取子线程执行结束后的返回值。
五、线程状态管理
1、线程睡眠---sleep:
2、线程让步---yield:
3、线程合并---join:
4、停止线程:
特殊情况:当线程处于了冻结状态,就不会读取到标记,也就不会结束。当没有指定方法让冻结的线程回复到运行状态时,我们需要对冻结状态进行清除,也就是强制让线程恢复到运行状态中来,这样可就可以操作标记让线程结束。
Thread类提供该方法: interrupt();
六 为什么要进行线程同步?
java允许多线程并发控制,当多个线程同时操作一个可共享资源变量时(如对其进行增删改查操作),会导致数据不准确,而且相互之间产生冲突。所以加入同步锁以避免该线程在没有完成操作前被其他线程调用,从而保证该变量的唯一性和准确性。
同步方法1:
同步函数:就是用synchronize关键字修饰的方法。因为每个java对象都有一个内置锁,当用synchronize关键字修饰方法时内置锁会保护整个方法,而在调用该方法之前,要先获得内置锁,否则就会处于阻塞状态。
同步方法2:
同步代码块:就是拥有synchronize关键字修饰的语句块,被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。
七、死锁
进程A中包含资源A,进程B中包含资源B,A的下一步需要资源B,B的下一步需要资源A,所以它们就互相等待对方占有的资源释放,所以也就产生了一个循环等待死锁。
避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。
线程池中的几种重要的参数
corePoolSize:核心池的大小
maximumPoolSize:线程池最大线程数
keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止
workQueue:一个阻塞队列
threadFactory:用于设置创建线程的工厂
三、几种重要的接口和类简介
1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
2、Set(无序、不能重复)
Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。
3、Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
17.在Java中,HashMap是如何工作的?
HashMap在Map.Entry静态内部类实现中存储key-value对。HashMap使用哈希算法,在put和get方法中,它使用hashCode()和equals()方法。当我们通过传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。Entry存储在LinkedList中,所以如果存在entry,它使用equals()方法来检查传递的key是否已经存在,如果存在,它会覆盖value,如果不存在,它会创建一个新的entry然后保存。当我们通过传递key调用get方法时,它再次使用hashCode()来找到数组中的索引,然后使用equals()方法找出正确的Entry,然后返回它的值。下面的图片解释了详细内容。
其它关于HashMap比较重要的问题是容量、负荷系数和阀值调整。HashMap默认的初始容量是32,负荷系数是0.75。阀值是为负荷系数乘以容量,无论何时我们尝试添加一个entry,如果map的大小比阀值大的时候,HashMap会对map的内容进行重新哈希,且使用更大的容量。容量总是2的幂,所以如果你知道你需要存储大量的key-value对,比如缓存从数据库里面拉取的数据,使用正确的容量和负荷系数对HashMap进行初始化是个不错的做法。
21.HashMap和HashTable有何不同?
(1)HashMap允许key和value为null,而HashTable不允许。
(2)HashTable是同步的,而HashMap不是。所以HashMap适合单线程环境,HashTable适合多线程环境。
(3)在Java1.4中引入了LinkedHashMap,HashMap的一个子类,假如你想要遍历顺序,你很容易从HashMap转向LinkedHashMap,但是HashTable不是这样的,它的顺序是不可预知的。
(4)HashMap提供对key的Set进行遍历,因此它是fail-fast的,但HashTable提供对key的Enumeration进行遍历,它不支持fail-fast。
(5)HashTable被认为是个遗留的类,如果你寻求在迭代的时候修改Map,你应该使用CocurrentHashMap。
25.ArrayList和LinkedList有何区别?
ArrayList和LinkedList两者都实现了List接口,但是它们之间有些不同。
(1)ArrayList是由Array所支持的基于一个索引的数据结构,所以它提供对元素的随机访问,复杂度为O(1),但LinkedList存储一系列的节点数据,每个节点都与前一个和下一个节点相连接。所以,尽管有使用索引获取元素的方法,内部实现是从起始点开始遍历,遍历到索引的节点然后返回元素,时间复杂度为O(n),比ArrayList要慢。
(2)与ArrayList相比,在LinkedList中插入、添加和删除一个元素会更快,因为在一个元素被插入到中间的时候,不会涉及改变数组的大小,或更新索引。
(3)LinkedList比ArrayList消耗更多的内存,因为LinkedList中的每个节点存储了前后节点的引用。
3、SpringMVC运行原理
流程说明:
(1)客户端(浏览器)发送请求,直接请求到DispatcherServlet。
(2)DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
(3)解析到对应的Handler后,开始由HandlerAdapter适配器处理。
(4)HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。
(5)处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。
(6)ViewResolver会根据逻辑View查找实际的View。
(7)DispaterServlet把返回的Model传给View。
(8)通过View返回给请求者(浏览器)
Spring的加载过程
容器启动的时候,web,xml中spring的监听器监听到容器启动,加载spring的配置文件,创建bean,加载到容器中。
在一个基于springmvc的web应用中,需要有一个web容器,一般我们用tomacat,这个web容器提供了一个全局的上下文环境ServletContext,同时也是Spring IoC容器的宿主环境。
宿主容器启动时,其入口文件便是web.xml。web.xml需要定义两个最基本的内容,ContextLoaderListener和DispatcherServlet。
1、ContextLoaderListener是实现了ServletContextListener接口的监听器,在项目启动的时候会触发容器初始化方法contextInitialized,容器初始化方法主要做3个事情
(1)执行initWebApplicationContext方法,启动一个根上下文WebApplicationContext(一个接口类),其实现类为XmlWebApplicationContext(即传说的IOC容器)。
(2)根据配置路径加载spring文件创建Bean的实例,这些bean都放入XmlWebApplicationContxt容器中。
(3)将加载好Bean实例的WebApplicationContext按指定的key注册到ServletContext(Java Web全局变量宿主容器)容器中去。
2、contextLoaderListener监听器监听容器初始化完成之后,开始初始化web.xml中配置的Servlet(可以配置多个),springmvc中以DispatcherServlet为例。DispatcherServlet,前端控制器,也可以叫请求分发控制器,用来接收、匹配、处理、转发每个servlet请求。DispatcherServlet会以WebApplicationServlet作为自己的parent上下文,然后再初始化自己的上下文。DispatcherServlet初始化上下文主要包括处理器映射器,处理器适配器,视图解析器等。最后再将初始化完成的Servlet注册到ServletContext中,这样每个Servlet都可以持有自己的上下文,同时又能共享根上下文,即IOC容器上下文WebApplicationContext。
设计模式
https://www.cnblogs.com/feifeicui/p/10431161.html
单例,简单工厂,代理模式,策略模式,适配器模式
Redis支持哪几种数据类型?
String、List、Set、Sorted Set、hashes
网点信息
key 网点code、 value 网点entity、
|
角色说明 |
Provider |
暴露服务的服务提供方 |
Consumer |
调用远程服务的服务消费方 |
Registry |
服务注册与发现的注册中心 |
Monitor |
统计服务的调用次调和调用时间的监控中心 |
Container |
服务运行容器 |
调用关系说明
-
服务容器负责启动,加载,运行服务提供者。
-
服务提供者在启动时,向注册中心注册自己提供的服务。
-
服务消费者在启动时,向注册中心订阅自己所需的服务。
-
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送
变更数据给消费者。
-
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如
果调用失败,再选另一台调用。
-
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数
据到监控中心。
1 自我介绍
2介绍自己开发遇到的困难,平常工作中遇到的问题,最棘手的问题怎么处理
3.值传递和引用传递的概念和区别;
值传递不会影响参数的值,引用传递会改变实际参数的值。
方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作
都是对形参这个值的修改,不影响实际参数的值。
方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;
在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
4.web service的思路;
服务提供者提供服务,并通过Web服务中介者发布,在注册中心注册
服务请求者向服务中介请求特定的服务,中介者根据请求查询注册中心寻找满足请求的服务
服务中介者返回满足条件的web服务信息给服务请求者,这个描述信息用wsdl写成
返回的描述信息生产相应的soap消息发送给请求者,实现服务的调用
服务提供者按soap消息执行相应的web服务,并将结果返回给请求者
5.如何用代码实现http请求;
域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码
--> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户
6.xml,html的不同点;
1 html用来显示数据,xml用来描述数据
2 xml比html 语法要求更严格
3 html与数据库没有直接联系 xml与数据库均可对应和转换
7.jquery ajax请求如何实现;
$.ajax() , $.get() , $.post()
8.如何解析xml;
DOM,SAX,JDOM,DOM4J
9. http 403,502,500的含义;
302:临时重定向
403:服务器拒绝请求
500:服务器内部错误
200:请求成功
404:页面无法找到
502:服务器网关错误
10 js的加载优化
将<script>标签放在页面底部,也就是</body>之后,确保页面都加载完成后再加载JS
合并脚本代码,页面中 <script>标签,越少越好
11多态的理解 实现在哪些地方
多态就是说允许不同子类型的对象对同一消息做出不同的反应
方法重载,方法重写
举一个简单的例子:比如说有个物流管理系统中,有两种用户:订购客户和卖方客户,两个客户都可以登录系统,他们有相同的方法login,
但登陆之后他们会进入不同的页面,也就是在登录的时候会有不同的操作,两种客户都继承父类的login方法,但对于不同的对象,拥有不同的操作。
12方法重载和方法重写(覆盖)的区别?
相同点:都属于多态机制
不同点:重载发生在同一个类中,方法名相同,参数列表不同。
重写发生在继承类中,方法名和参数列表相同,权限修饰符大于等于父类、返回值类型,抛出异常小于等于父类。
13 spring的原理及作用
spring有2个核心技术,ioc控制反转或者说叫DI依赖注入和aop面向切面编程。我先说一下IOC,当某个java实例(调用者)需要调用另一个java实例(被调用者)时,传统情况下,
通过new来创建被调用者的实例,
而在依赖注入的模式下创建被调用者的工作不再由调用者来完成,因此称之为"控制反转";创建被调用者实例的工作通常由Spring来完成,然后注入调用者,所以也称之为"依赖注入"。
设置注入:IoC容器使用属性的setter方式注入被依赖的实例,
构造注入:IoC容器使用构造器来注入被依赖的实例
我再说一下aop,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,减少系统的重复代码,降低模块间的耦合度,让代码更易于维护。
程序中的一个管理者,整个程序的运行都依靠spring来管理
通过spring管理持久层的mapper(相当于dao接口)
通过spring管理业务层service,service中可以调用mapper接口,并对事务进行控制。
通过spring管理表现层Handler,Handler中可以调用service接口。
14 spring的事务 事务的隔离级别
我先说一下什么是事务,事务就是一组操作,组成这组操作的各个操作,要么一 起成功,要么一起失败.事务有四个特性:
原子性 (atomicity):强调事务的不可分割.
一致性 (consistency):事务的执行的前后数据的完整性保持一致.
隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库
如果不考虑事务隔离性引发安全性问题:
脏读 :一个事务读到了另一个事务的未提交的数据
不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致.
虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致.
15 Spring支持五种事务隔离级别:
DEFAULT:使用数据库本身使用的隔离级别 ORACLE(读已提交) MySQL(可重复读)
READ_UNCOMITTED:读未提交(脏读)最低的隔离级别,一切皆有可能。
READ_COMMITED:读已提交,ORACLE默认隔离级别,有幻读以及不可重复读风险。
REPEATABLE_READ:可重复读,解决不可重复读的隔离级别,但还是有幻读风险。
SERIALIZABLE:串行化,最高隔离级别,杜绝一切隐患,缺点是效率低。
16 springmvc
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
17 springmvc与Struts2的区别
spring mvc的入口是servlet,而struts2是filter
Struts2框架是类级别的拦截,SpringMVC是方法级别的拦截
SpringMVC开发效率和性能高于Struts2
Struts2用的拦截机制是Interceptor,SpringMVC这是用的是独立的Aop方式
struts配置文件比较多,springmvc可以认为是零配置
18 restful风格
(1)每一个URI代表一种资源,独一无二
(2)客户端和服务器之间,传递这种资源的某种表现层
(3)客户端通过四个GET、POST、PUT和DELETE方法对服务器端资源进行操作,实现"表现层状态转化"。
19 dubbo四大组件
Provider:提供者
Consumer:消费者
registry:注册中心(相当于中介)
monitor:监控中心
提供者在容器启动时,向注册中心注册自己提供的服务,
消费者在启动时,向注册中心订阅自己所需的服务
注册中心返回提供者地址列表给消费者
消费者从提供者地址列表中,选一台提供者进行调用
消费者和提供者在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
用过什么数据库,怎么优化,sql的聚合函数,sql优化,常用数据库函数;数据连接池的种类,如何配置; 数据库索引 怎么让索引失效,怎样在数据库添加成员
20 mysql和oracle
这个优化法则归纳为5个层次:
1、 减少数据访问(减少磁盘访问)
创建并使用正确的索引,只通过索引访问数据
2、 返回更少数据(减少网络传输或磁盘访问)
数据分页处理,只返回需要的字段
3、 减少交互次数(减少网络传输)
批量提交数据,id in list
4、 减少服务器CPU开销(减少CPU及内存开销)
使用绑定变量,合理使用排序,减少比较操作
21sql优化
索引并不是越多越好,索引提高相应的查询效率,但同时也降低了 insert 及 update 的效率
1 避免全表扫描,首先应考虑在 where 及 order by 用到的列上建立索引
2 避免在 where 子句中使用!=或<>操作符,避免对字段进行 null 值判断,避免使用 or 来连接条件,否则索引失效
3 避免在 where 子句中使用in 和 not in,like等进行模糊查询
4 避免在 where 子句中使用 or 来连接条件,否则索引失效
5 用具体的字段列表代替“*”,不要返回用不到的任何字段
22 常用函数
AVG --求平均值
COUNT --统计数目
MAX --求最大值
MIN --求最小值
SUM --求和
23 数据连接池的种类
DBCP
C3PO
Proxool
BoneCP
24 在数据库添加成员
--创建了一个名为:test 密码为:1234 的用户
create user 'test'@'localhost' identified by '1234';
--授予用户test通过外网IP对数据库“testdb”的全部权限
grant all privileges on 'testdb'.* to 'test'@'%' identified by '1234';
--刷新权限
flush privileges;
--授予用户“test”通过外网IP对于该数据库“testdb”中表的创建、修改、删除权限,以及表数据的增删查改权限
grant create,alter,drop,select,insert,update,delete on testdb.* to test@'%';
25 redis的数据类型, 优点和缺点
string(字符串) list(列表) hash(散列) sets (集合) sorted set(有序集合)
26 redis优点
a.单线程,利用redis队列技术并将访问变为串行访问,消除了传统数据库串行控制的开销
b.redis具有快速和持久化的特征,速度快,因为数据存在内存中。
c.分布式 读写分离模式
d.支持丰富数据类型
e.支持事务,操作都是原子性,所谓原子性就是对数据的更改要么全部执行,要不全部不执行。
f.可用于缓存,消息,按key设置过期时间,过期后自动删除
mybatis工作原理
mybatis应用程序通过SqlSessionFactoryBuilder从配置文件中读取配置信息,构建出SqlSessionFactory;
然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。
27 mybatis的一级缓存和二级缓存 二级缓存的替代方式 mybatis动态sql的实现 #和$区别
①、一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的
缓存数据区域(HashMap)是互相不影响的。
②、二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
二级缓存的替代方式 redis替代
28 mybatis动态sql的实现
1. if 语句 (简单的条件判断)
2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似.
3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)
4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or ,不必担心多余导致语法错误)
5. set (主要用于更新时)
6. foreach (在实现 mybatis in 语句查询时特别有用)
29 #和$区别
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
2. $将传入的数据直接显示生成在sql中。
3.$方式一般用于传入数据库对象,例如传入表名.
4 一般能用#,#方式能够防止sql注入
30 场景:10个订单 for循环入库 如果第三条到第三条异常,怎么保证后面的都正常
try catch
31 i++是先赋值,然后再自增;++i是先自增,后赋值。
32 .集合类的相同/不同点;arraylist和linkedlist的区别和联系;
hashmap的原理 说一下 线程安全的map hashtab和hashmap的区别 ConcurrentHashMap的实现 他的锁是怎么实现的
33 HashTable与HashMap
相同点:
(1)都实现了Map<K,V>, Cloneable, Serializable 接口。
(2)都是存储"键值对(key-value)"的散列表,而且都是采用拉链法实现的。
不同点:
(1)同步性:HashTable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的 。
(2)对null值的处理:HashMap的key、value都可为null,HashTable的key、value都不可为null 。
(3)基类不同:HashMap继承于AbstractMap,而Hashtable继承于Dictionary。
(4)支持的遍历种类不同:HashMap只支持Iterator(迭代器)遍历。而Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。
34 ConcurrentHashMap 是一个二级哈希表。在一个总的哈希表下面,有若干个子哈希表。
ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,
当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
35 线程的运行状态
线程五种状态(新建、就绪、运行、阻塞、死亡)
36 怎么保证线程安全
1 使用synchronized关键字:
2 使用锁:
a.Lock使用起来比较灵活,但需要手动释放和开启;采用synchronized不需要用户去手动释放锁,
b.Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性
c.在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时Lock是个不错的方案。
37 volatile的理解
是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。
38 线程的通信是怎么实现的
一、传统线程通信synchronized + wait + notify
二、使用Condition控制线程通信lock + condition + await + signal
三、使用阻塞队列(BlockingQueue)控制线程通信
39 线程池的应用 都有哪几种线程池 线程池的参数
应用场景
1.单个任务处理的时间比较短
2.将需处理的任务的数量大
40
1、newCachedThreadPool 可缓存线程池
2、newFixedThreadPool 创建一个指定工作线程数量的线程池
3、newSingleThreadExecutor 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
4、newScheduleThreadPool 创建一个定长的线程池
41线程池参数
1、corePoolSize:核心线程数
2、queueCapacity:任务队列容量(阻塞队列)
3、maxPoolSize:最大线程数
4、 keepAliveTime:线程空闲时间
5、allowCoreThreadTimeout:允许核心线程超时
6、rejectedExecutionHandler:任务拒绝处理器
42线程池优缺点
1.减少在创建和销毁线程上所花的时间以及系统资源的开销
2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。
缺点是可能出现死锁
43反射的应用场景 举例
通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。
平时的项目开发过程中,基本上很少会直接使用到反射机制,但是实际上有很多设计、开发都与反射机制有关
举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;
②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:
1) 将程序内所有 XML 或 Properties 配置文件加载入内存中;
2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
3)使用反射机制,根据这个字符串获得某个类的Class实例;
4)动态配置实例的属性。
43序列化
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
44多线程的同步、缓存的保存与获取等等
1 同步方法synchronized关键字修饰的方法
2 同步代码块
3 使用特殊域变量(volatile)实现线程同步
4 使用重入锁实现线程同步
45怎么坚决死锁的问题,以及java内存溢出的处理方式
解决方式1:线程间通信–通过构造方法共享数据
2.通过构造方法共享数据,并使用 (等待–唤醒) 机制实现线程间通信
3.私有化锁对象的成员变量,自己提供get和set方法供外界调用
46java内存溢出的处理方式
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
第四步,使用内存查看工具动态查看内存使用情况
47说几个设计模式,
https://www.cnblogs.com/feifeicui/p/10431161.html
48 jvm的内存结构
方法区(也就是"持久代"),java8里彻底被移除,取而代之的是元数据区
堆
栈
PC寄存器
49 java垃圾回收机制?
在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,
才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。
50 java中垃圾收集的方法有哪些?
标记-清除:
复制算法:
标记-整理
分代收集
简述java类加载机制?
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型。
12.linux,查询java进程的命令;
ps -ef|grep java
52接口,抽象类
接口是用来实现类间多重继承功能的结构.
接口不能实例化,即不能用new运算符创建对象。
一个类通过使用关键字implements声明自己实现一个或多个接口。
在类体中可以使用接口中定义的常量,而且必须实现接口中定义的所有方法
接口中的方法是自动公有的,接口中的方法都是抽象的。
抽象类必须使用abstract修饰符来定义,抽象方法也必须用abstract来修饰。
抽象类不能被实例化,不能用new关键字去产生对象。
抽象方法只能声明,不能实现。
含有抽象方法的类必须被声明为抽象类,抽象类的子类必须覆盖所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。
53Java的8种基本数据类型
byte,short,int,long,float,double,char,boolean
54 jvm类加载的过程
类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。
其中类加载过程包括加载、验证、准备、解析和初始化五个阶段。
类加载阶段就是由类加载器根据一个类名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
验证类数据信息是否符合JVM规范
为类中的所有静态变量分配内存空间,并为其设置一个初始值
将常量池中的符号引用转为直接引用
如何优化一条sql
第一步:理解sql业务,逻辑上是否可以优化
第二部:explain sql执行计划,目测有没有该走的索引没有走
第三部:查看有无常见影响效率的错误,如null,列上使用函数,or不走组合索引,join之前减少join列数
第四部:增加合适的索引
第五步:还不行,尝试限制需求(如只可以统计指定范围数据)或者其他方式实现(如定时任务定时分析一批)
第六步:数据量超大,只可以考虑分表分库等手段了。
1 代码review怎么做的
用到一款插件工具findbugs
1 代码中的一些坏习惯
类名的命名,以大写字母开头, 方法名以小写字母开头, 字段名以小写字母开头
2 糟糕的代码
对象创建了并没有用
3 关于代码性能相关方面的
字符串转换成int 应该使用Integer.parseInt(“”) 代替Integer.valueOf(“”)
4 代码正确性相关方面的
多线程使用本事就是不安全的,改进方法:需要创建多实例或线程同步