2019面试总结
2019-05-22 12:08 晨曦曙光 阅读(532) 评论(0) 编辑 收藏 举报1.线程和进程的定义
定义:
进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。
线程:是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。
注:一个程序至少一个进程,一个进程至少一个线程。
区别:
地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间
资源拥有:同一进程内的线程共享本进程的资源如内存、I/O、cpu等,但是进程之间的资源是独立的。
优缺点:
线程执行开销小,但是不利于资源的管理和保护。线程适合在SMP机器(双CPU系统)上运行。
进程执行开销大,但是能够很好的进行资源管理和保护。进程可以跨机器前移。
使用场景:
对资源的管理和保护要求高,不限制开销和效率时,使用多进程。
要求效率高,频繁切换时,资源的保护管理要求不是很高时,使用多线程
2.NIO和AIO的区别;
AIO 是彻底的异步通信。
NIO 是同步非阻塞通信。
3.HTTP协议、TCP协议、IP协议和TCP/IP协议区别
TCP/IP:协议叫做网络通信协议,它包括上百个协议,而HTTP协议、TCP协议、IP协议只是TCP/IP协议中的一部分.
TCP协议:是一种面向连接的、可靠的、基于字节流的{传输层}通信协议
注:tcp链接需要三次握手:
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了
注:tcp 关闭需要4次挥手:
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
IP协议:是无连接的通信协议,负责将每个包路由至它的目的地。
HTTP协议:是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统
4.kafka的架构和几个模块组成
Broker:Kafka 集群包含一个或多个服务器,这种服务器被称为 broker。
Topic:每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic。
Partition:Partition 是物理上的概念,每个 Topic 包含一个或多个 Partition。
Producer:负责发布消息到 Kafka broker。
Consumer:消息消费者,向 Kafka broker 读取消息的客户端。
Consumer Group:每个 Consumer 属于一个特定的 Consumer Group(可为每个 Consumer 指定 group name,若不指定 group name 则属于默认的 group)。
5.ioc是什么,有几种注入方式
IOC:所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系
5.2注入方式:
(1)使用属性的setter方法注入 这是最常用的方式(xml注入dao层);
(2)使用构造器注入;
(3)使用Filed注入(用于注解方式)
主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:
@Component:可以用于注册所有bean
@Repository:主要用于注册dao层的bean
@Controller:主要用于注册控制层的bean
@Service:主要用于注册服务层的bean
6.hashmap和hashtab的区别
hashtab:底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低
hshmap:底层数组+链表实现,可以存储null键和null值,线程不安全
7.MySQL优化
1. 为查询缓存优化你的查询
2.字段建索引
3.避免 SELECT *
4.远为每张表设置一个ID
5.用 ENUM 而不是 VARCHAR
6.可能的使用 NOT NULL
7固定长度的表会更快
8 拆分大的 DELETE 或 INSERT 语句
9 设计合适的索引,基于主键的查找,上亿数据也是很快的;
10反范式化设计,以空间换时间,避免join,有些join操作可以在用代码实现,没必要用数据库来实现;
11buffer,尽量让内存大于数据.
8.netty的架构
Netty是基于Java NIO client-server的网络应用框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议。Netty提供了一种新的方式来开发网络应用程序,这种新的方式使它很容易使用和具有很强的扩展性。Netty的内部实现是很复杂的,但是Netty提供了简单易用的API从网络处理代码中解耦业务逻辑。Netty是完全基于NIO实现的,所以整个Netty都是异步的 。
9同步、异步,同步阻塞、同步非阻塞
同步和异步:
同步:在发出一个同步调用时,在没有得到结果之前,该调用就不返回。
异步:在发出一个异步调用后,调用者不会立刻得到结果,该调用就返回了。
阻塞和非阻塞:
阻塞调用是指调用结果返回之前,调用者会进入阻塞状态等待。只有在得到结果之后才会返回。
非阻塞调用是指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
并发和并行:
并发是指一个时间段内,有几个程序都在同一个CPU上运行,但任意一个时刻点上只有一个程序在处理机上运行。
并行是指一个时间段内,有几个程序都在几个CPU上运行,任意一个时刻点上,有多个程序在同时运行,并且多道程序之间互不干扰
10.rocitmq和kafka的区别以及Kafka的性能
11.javaMap的遍历方式
12.es不适用什么场景
14.int[] arr=new int[0]打印的是对象还是引用
15.MySQL引擎的区别
16.MySQL使用个8个lift jion会怎么样
17.秒杀架构的设计
19.arrysList边遍历边删除值该怎么做(使用同一个list)
20.mysql 的分库和分表
21.Java有了垃圾回收机制为什么还会出现内存泄漏
22.linux系统的模块
linux系统一般分为4个主要部分:内核、shell+库、文件系统和应用.
23.在数据量单线程能满足的情况下使用单线程好,还是多线程好。
思路:多线程的线程调用十分耗cpu,多线程调用线程的调用要保存起来所以耗费内存
24.springcloud和duboo的区别
通信方式:
dubbo是纯粹的RPC框架,实现远程服务调用。spring cloud采用的是其于HTTP 的 REST方式。 严格来说,这两种方式各有优劣。虽然从一定程度度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。
而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依堂一纸契约,不存在代码级的强依赖,这在强调快速微服务环境下,显得更加合适。这也是dubbo和spring cloud最本质的区别
架构:
spring cloud比dubbo的功能更完善,涵盖更广,而且作为spring的拳头产品,它能与spring framework,spring boot,springdata等其他spring项目完美融合,使用dubbo就像组装电脑,各个环节的自由度很高,例如注册中心,可以用zookeeper,redis等。spring cloud就像品牌机,在spring source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性
25.MySQL和postgresql的区别
PG相对于MySQL的优势:
1、在SQL的标准实现上要比MySQL完善,而且功能实现比较严谨;
2、存储过程的功能支持要比MySQL好,具备本地缓存执行计划的能力;
3、对表连接支持较完整,优化器的功能较完整,支持的索引类型很多,复杂查询能力较强;
4、PG主表采用堆表存放,MySQL采用索引组织表,能够支持比MySQL更大的数据量。
5、PG的主备复制属于物理复制,相对于MySQL基于binlog的逻辑复制,数据的一致性更加可靠,复制性能更高,对主机性能的影响也更小。
6、MySQL的存储引擎插件化机制,存在锁机制复杂影响并发的问题,而PG不存在。
MySQL相对于PG的优势:
1、innodb的基于回滚段实现的MVCC机制,相对PG新老数据一起存放的基于XID的MVCC机制,是占优的。新老数据一起存放,需要定时触 发VACUUM,会带来多余的IO和数据库对象加锁开销,引起数据库整体的并发能力下降。而且VACUUM清理不及时,还可能会引发数据膨胀;
2、MySQL采用索引组织表,这种存储方式非常适合基于主键匹配的查询、删改操作,但是对表结构设计存在约束;
3、MySQL的优化器较简单,系统表、运算符、数据类型的实现都很精简,非常适合简单的查询操作;
4、MySQL分区表的实现要优于PG的基于继承表的分区实现,主要体现在分区个数达到上千上万后的处理性能差异较大。
5、MySQL的存储引擎插件化机制,使得它的应用场景更加广泛,比如除了innodb适合事务处理场景外,myisam适合静态数据的查询场景。
总体上来说,开源数据库都不是很完善,商业数据库oracle在架构和功能方面都还是完善很多的。从应用场景来说,
PG更加适合严格的企业应用场景(比如金融、电信、ERP、CRM),
而MySQL更加适合业务逻辑相对简单、数据可靠性要求较低的互联网场景(比如google、facebook、alibaba)
26.jvm(java)的内存结构
JVM把内存划分成了如下几个区域:
1.方法区(Method Area):方法区存放了要加载的类的信息(如类名、修饰符等)、静态变量、构造函数、final定义的常量、类中的字段和方法等信息。方法区是全局共享的,在一定条件下也会被GC。当方法区超过它允许的大小时,就会抛出OutOfMemory:PermGen Space异常。
2.堆区(Heap): 堆区是GC最频繁的,也是理解GC机制最重要的区域。堆区由所有线程共享,在虚拟机启动时创建。堆区主要用于存放对象实例及数组,所有new出来的对象都存储在该区域。
3.虚拟机栈(VM Stack): 虚拟机栈占用的是操作系统内存,每个线程对应一个虚拟机栈,它是线程私有的,生命周期和线程一样,每个方法被执行时产生一个栈帧(Statck Frame),栈帧用于存储局部变量表、动态链接、操作数和方法出口等信息,当方法被调用时,栈帧入栈,当方法调用结束时,栈帧出栈。
注:虚拟机栈定义了两种异常类型:StackOverFlowError(栈溢出)和OutOfMemoryError(内存溢出)。如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StackOverFlowError;不过大多数虚拟机都允许动态扩展虚拟机栈的大小,所以线程可以一直申请栈,直到内存不足时,抛出OutOfMemoryError。
4.本地方法栈(Native Method Stack):本地方法栈用于支持native方法的执行,存储了每个native方法的执行状态。本地方法栈和虚拟机栈他们的运行机制一致,唯一的区别是,虚拟机栈执行Java方法,本地方法栈执行native方法。在很多虚拟机中(如Sun的JDK默认的HotSpot虚拟机),会将虚拟机栈和本地方法栈一起使用。
5.程序计数器(Program Counter Register):程序计数器是一个很小的内存区域,不在RAM上,而是直接划分在CPU上,程序猿无法操作它,它的作用是:JVM在解释字节码(.class)文件时,存储当前线程执行的字节码行号,只是一种概念模型,各种JVM所采用的方式不一样。字节码解释器工作时,就是通过改变程序计数器的值来取下一条要执行的指令,分支、循环、跳转等基础功能都是依赖此技术区完成的。
引用的种类:
强引用:new出来的对象都是强引用,GC无论如何都不会回收,即使抛出OOM异常。
软引用:只有当JVM内存不足时才会被回收。
弱引用:只要GC,就会立马回收,不管内存是否充足。
虚引用:可以忽略不计,JVM完全不会在乎虚引用。它唯一的作用就是做一些跟踪记录,辅助finalize函数的使用。
什么样的类会被回收:
a.该类的所有实例都已经被回收;
b.加载该类的ClassLoad已经被回收;
c.该类对应的反射类java.lang.Class对象没有被任何地方引用。
GC机制:在上面介绍的五个内存区域中,有3个是不需要进行垃圾回收的:本地方法栈、程序计数器、虚拟机栈。因为他们的生命周期是和线程同步的,随着线程的销毁,他们占用的内存会自动释放。所以,只有方法区和堆区需要进行垃圾回收,回收的对象就是那些不存在任何引用的对象。
内存分区:
新生代(Youn Generation):大致分为Eden区和Survivor区,Survivor区又分为大小相同的两部分:FromSpace和ToSpace。新建的对象都是从新生代分配内存,Eden区不足的时候,会把存活的对象转移到Survivor区。当新生代进行垃圾回收时会出发Minor GC(也称作Youn GC)。
旧生代(Old Generation):旧生代用于存放新生代多次回收依然存活的对象,如缓存对象。当旧生代满了的时候就需要对旧生代进行回收,旧生代的垃圾回收称作Major GC(也称作Full GC)。
持久代(Permanent Generation):在Sun 的JVM中就是方法区的意思,尽管大多数JVM没有这一代。
参考地址:https://blog.csdn.net/anjoyandroid/article/details/78609971
27.Synchronize 和 Lock 的区别
>1.原始构成
synchronized 是关键字属于JVM层面,
monitorenter(底层是通过monitor对象来完成,其实wait/notify等方法也依赖于monitor对象只有在同步块或方法中才能调wait/notify等方法,)
monitorexit
Lock是具体类(java.util.concurrent.locks.Lock)是api层面的锁
>2.使用方法
synchronized 不需要用户去手动释放锁,当synchroized代码执行完成后系统会自动让线程释放对锁的占用
ReentrantLock则需要用户去手动释放锁若没有主动释放锁,就有可能导致出现死锁现象。(需要lock()和unlock()方法配合try/finally语句块来完成。)
>3.等待是否可中断
synchronized不可中断,出非抛出异常或者正常运行完成
ReentrantLock可中断:1.设置超时方法try lock(long timeout,TimeUnit unit)2.lockInterruptibly()放代码块中,调用interrupt()方法可中断
>4.加锁是否公平
synchronized是非公平锁
ReentrantLock两者皆可,默认非公平锁,构造方法可以传入boolean值,true为公平锁,false为非公平锁
>5.锁绑定多个条件
synchronized 没有
ReentrantLock用来实现分组唤醒的线程们,可以精确唤醒。而不是像synchronized要么随机唤醒一个线程要么唤醒全部。