你好,我是**,来自***,***,我应聘的岗位是***。
入学期间主要掌握的语言是***,在学校学习了网络,数据库和数据结构等专业课。
为什么使用dubbo
如电商网,单一的MVC架构,在开发的时候,占用的内存越来越多,维护也难以维护,随意产生了垂直
应用架构。解决了单一应用架构所面临的扩容问题,流量能够分割到各个子系统当中,且系统的体积
可控,降低了维护成本,提升了开发效率。
公共的逻辑业务提取出来形成服务,对外提供。
让前端业务系统和底层数据访问分离,团队分工明确。
dubbo在整个分布式系统架构中,分层的架构来架构,使每一层之间最大限度的松耦合。
连接:https://blog.csdn.net/yu876876/article/details/81560122
TCP的三次握手
1.客户端发送SYN给服务器,客户端进入SYN_SENT状态,等待服务器确认。
2.服务器收到数据包后,发送SYN和ACK给客户端,确认连接请求,服务器进入SYN_REVD状态。
3.客户端收到确认后,将发送ACK给服务器,服务器检查ACK为1,则连接建立成功。可以传输数
据。
问题衍生:
1.为什么建立连接是三次握手,而不是四次呢?
第一次握手:客户端什么也不能确认,服务器端确认了对方发送的是正常的。
第二次握手:客户端确认了自己的发送和接收是正常的,对方的发送和接收也是正常的。
服务器端确认了自己的接收正常,对方的发送正常。
第三次握手:客户端确认了自己的发送和接收正常,对方的发送和接收正常。
服务器端确认了,自己的发送和接收正常,对方的发送和接收也正常。
所以没有必要再进行第四次的握手,当然想要四次握手也不是不可以。
2.TCP两次握手为什么不可以
二次握手,假设A发送一个数据给B,发生了延迟,时间超过了计时器的时间,于是A认为这个数据
丢失了,然后重新发了消息,当A和B的通信结束了,A认为丢失的消息到达了B,对于B而言,认为
这是一个新的连接信息,就像A发送了确认,对A而言,因为他认为没有给B发送消息,所以A不会理
睬B的确认,但是握手连接已经成功,B会一直等待A的消息。这就导致了B的事件浪费,所以产生了
三次握手。
三次握手也防止了已经失效的请求报文段,突然又传到了服务端而产生的连接误判。
为什么TCP要四次挥手
1.客户端发送FIN,用来关闭客户端到服务器的数据传送,此时客户端进入FIN-WAIT_1(终止等待
1)终止状态
2.服务器接收到了FIN后,发送一个ACK给客户端,服务器进入Close_WAIT(关闭等待)状态,客
户端接收到了ACK后,客户端进入FIN-WAIT-2(终止等待2)状态。
3.服务器发送一个FIN,用来关闭Server到Client的数据的传送,服务器进,入LAST_ACK(最后
确认)状态。
4.客户端收到FIN后,客户端进入到了TIME_WAIT状态,需要经过发送ACK给服务器,但是此时连
接还没有被释放,必须经过2*MSL(最长报文段寿命)才会被释放。服务器接收到了ACK后,服务器
进入CLOSED状态。
问题衍生:
1.为什么TIME_WAIT状态需要经过2MSL才能回到CLOSED状态:
因为假设网络不可靠,有可能最后一个ACK丢失,所以TIME_WAIT是为了用来重发可能丢失的ACK
报文。在客户端发送最后的ACK回复,该ACK可能丢失。服务器没有收到ACK会重复发送FIN。所以
客户端不能立即关闭,他必须确认服务器收到了该ACK。所以客户端在发送ACK之后会进入
TIME_WAIT状态,客户端设置一个计时器,等待2MSL时间,因为MSL是一个片段在网络中存活的最
长时间,2MSL是发送和回复所需要的最大事件。如果直到2MSL客户端都没有收到FIN,则客户端推
断ACK已经被成功接收了,可以结束TCP连接了。
2.如果建立连接之后,客户端突然出现故障怎么办?
TCP设有一个保活计时器,客户端出现故障以后,服务器不能一直等下去,服务器每次收到客户端
的请求都会重新复位这个计时器,时间通常是2个小时,如果两个小时还没有收到客户端的
任何数据,服务器会发送一个探测报文段,以后每隔75S就会发送一次,若一连发送10个探测报文
还没有反应,服务器就认为客户端出现了故障,接着就会关闭连接。
final,finalize,finally的区别
1.final是java的关键字,当一个类声明为final,则不能被继承;一个方法被声明为final则不
能被重写重载,一个变量被声明为final则意味着不能被改变。
2.finalize 是java的一个方法名,finalize()方法在垃圾收集器将对象从内存中清除出去前,
做必要的清理工作。子类覆盖fianlize()方法以整理系统资源或者执行其他清理工作。
finalize()是在垃圾收集器删除对象之前对这个对象调用的。
3.finally:是java的一种异常处理机制,是对java异常处理模型的最佳补充。finally结构使代
码总会被执行。可以维护对象内部状态,并可以清理非内存资源。
单例
懒汉用时间换空间,每一次获取实例都会判断是否要进行创建实例。
饿汉,空间换时间,不管用不用都会先创建出实例,每次调用的时候就不需要判断了。
不加同步的懒汉式是不安全的,而因为虚拟机只保证装载了一次,所以装载累的额时候,不会发生并发,所以饿汉是安全的。
懒汉要是想保证线程安全可以使用synchronized,但是如果直接给类加上同步锁,会降低整个访问速度。所以可以使用双重检查锁。
删除重复节点
删除排序链表中的重复节点
样例输入 1 2 3 3 4 4 5
输出 1 2 3 4 5
1.新建一个头结点,以防第一个节点被删除。
2.保存当前节点上个节点,循环遍历整个链表,如果当前节点的值和下一个节点的值相等,则将
当前节点的值与next.next比较,直到不相等或者null为止,最后当当前节点的上个节点pre指向最后比较不相等的节点。
3.如果当前节点与next节点不相等,则直接节点指针全部向后移动一位。
public class Delete{
public ListNode delete(ListNode pHead){
if(pHead==null){
return pHead;
}
ListNode first = new ListNode(0);//新建一个节点
first.next = pHead;
ListNode p = pHead;
ListNode pre = first;
while(p!=null&&p.next!=null){
if(p.val==p.next.val){
int val = p.val;
while(p!=null&&p.val==val){
p = p.next;
}
pre.next = p;
}else{
pre = p;
p = p.next;
}
}
return first.next;
}
}
MVC
MVC是应用程序的视图层划分出来的不同功能的几个模块。MVC主要是为了解决应用程序用户界面的样式替换问题,吧展示数据的HTML页面尽可能的和业务代码分离。MVC把纯净的页面展示逻辑(用户页面)独立到一些文件中(Views),把一些和用户交互的程序逻辑(controller)单独放在一些文件中,在Views和Controller中传递数据使用一些专门封装数据的实体对象,这些对象,统称为Models。MVC是为了解决BS应用程序视图层的部分耦合问题。
MVCC
第二个反向打印二叉树
redis用到了哪些接口
dubbo是什么能做什么?
是一个分布式服务架构,远程服务调用的分布式架构。可以基于注册中心目录服务,使消
费者方能动态的查找服务提供方,使地址透明,使服务提供者可以平滑增加或减少机器。
透明化的远程调用,就像调用本地方法一样调用远程的方法,只需要简单配置,没有任何
API侵入。而且服务自动注册和发现,不再需要写死服务提供方地址,注册中心基于接口
名查询服务提供者的IP地址,并且能够平滑的增加或删除服务提供者。
为什么使用redis做为缓存
redis是一个非关系性数据库。可以用作数据库,缓存和消息中间件。
常见的数据结构:String,list,hash,set,zset.
数据库的工作模式按存储方式可以分为,硬盘数据库和内存数据库。Redis将数据存储在内存中读写数据的时候不会受到硬盘I/O的速度限制所以很快。
为什么这么快?
1.完全基于内存,绝大部分的请求时纯粹的内存操作,非常快速。
2.数据结构简单,对数据操作简单。
3.采用单线程,避免了上下文切换和竞争条件。
4.使用多路I/O复用模型,非堵塞IO
问题衍生:
SSO为什么使用redis+cookie代替session:因为分布式有不同服务器,所以一般方式存储session,那么session会保存在某一台服
务器上,下一台请求不访问这个服务器就读取不到这个session的区别。
http和dubbo的区别
http是基于http协议的post和get接口
dubbo相当于调用本地节后一样调用远程服务的接口
1、索引
为了高效运行,所以可以提高mysql的检索速度。
索引类型:1.全文索引,为了解决针对文本的模糊查找效率低的问题。
2.hash索引,类似键值对的形式,一次定位,只在=,和in条件下速度快。
3.b树,一个节点可以有多个节点,每个节点存储data和key,一次查找相当于一次二分
查找,查询结果可能不会出现在叶子节点。
4.B+树一个节点有多个节点,除了叶子节点存储key和data以外其他节点存储Key.查询
结果一定存储在叶子节点,且叶子节点之间用指针相连,加快了顺序查找的速度。
索引的种类:
1.普通索引:仅仅加速查询
2.主键索引:加速查询+列值唯一(不可以有null)+表中只有一个
3.唯一索引:加速查询+列值唯一(可以有null)
4.联合索引,多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。
5.全文索引:对文本的内容进行分词搜索。
聚簇索引和非聚簇索引:
主索引文件和数据文件是同一份文件。聚簇索引中实际的数据保存在叶子页中,一个表只
有一个聚簇索引。
在列经常被分组排序和返回某范围内的数据中使用
优点:通过聚簇索引会直接获得数据,相对于非聚簇索引的二次查询,效率会更高。
缺点:更新代价高,如果更新了行的聚簇索引列,就需要将数据移动到相应的位置,这可
能是是因为要插入的也已满而导致的页分裂。
非聚簇索引:索引的叶子节点保存的不是数据本身而是数据存放的地址。表数据的存储顺
序和索引顺序无关,叶子节点中包含索引字段值以及指向数据行的逻辑指针。
在列经常被分组和大数目不同值中经常使用。
2、事务
ACID:主要是事务的四个特性,原子性,一致性,隔离性和持久性。
事务:数据库中,一个事务指的是一系列连续的数据库操作组成的一个完整的逻辑过程。
1.原子性:一个事务要么全成功要么全失败
2.一致性:事务执行前后,数据库的一致性约束没有被破坏。事务前后的完整性必须保持
3.隔离性:多个用户并发访问数据库,数据库为每一个用户开启的事务,不会被其他事务的操作干扰,多个并发用户之间相互隔离。
问题衍生:
如何实现事务隔离性:
1.读写锁:每次读操作都需要获取一个共享锁,每次写操作需要获取一个写锁。共享锁之间不会
发生互斥,共享锁和写锁之间,以及写锁和写锁之间会产生互斥。当产生锁竞争时,需要其中一个
操作释放锁后,另一个操作才能获取到锁。
2.MVCC多版本控制:为了提高并发效率,采取读写不冲突的方法,这个方法只有在写操作的时候才需要加行级锁,因此并发效率更高。MVCC的实现是通过保存数据在某个时间点的快照来实现的。每行数据都存在一个版本,每次数据更新时都更新该版本。修改时复制出当前版本随意更改,各个事务之间无干扰。保存时比较版本号,如果成功就覆盖,不成功回滚。
https://www.cnblogs.com/shoshana-kong/p/11244341.html未完待续
四个隔离级别:读写未提交,读写已提交,可重复读,串行化。
4.持久性:事务一旦提交,对数据库的数据的改变是永久性的。
脏读:一个事务读取了另外一个事务没有提交的数据
不可重复读:一个事务内读取表的某一行数据,多次读取结果不同。
幻读:一个事务读取了别的事务插入的数据,导致前后读取不一致。一般是行影响,多了一行
3、hashmap hashtable concurrenthashmap
hashTable:
·底层数组+链表实现,无论是key还是value都不可以为null,线程安全,实现线程安全
的方式是在修改数据的时候,锁住整个HashTable。效率低,concurrentHashMap做了
优化。
·初始size为11,扩容:newsize = oldsize*2+1
·计算index的方法,index = (hash & 0x7FFFFFFF)%length
HashMap:
·底层数组+链表实现,可以存储key为null和value为null,线程不安全
·初始size为16,扩容newsize = oldsize*2,size一定为2的n次幂
·当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配
更均匀。
concurrentHashMap:
jdk1.8以前采用分段的数组+链表来实现,线程安全。
·通过吧整个Map分为N个segment可以提供相同的线程安全,但是效率提高了N倍。默认提升16倍。
·Hashtable的synchronized是针对整张表,每次锁住整张表让线程独占,而
concurrentHashMap允许次改多个操作并发进行,关键在于使用锁分离技术。
Base:南京
1、自我介绍
2、项目中遇到的最大的难题,怎么解决的?
因为做的是一个分布式项目,最大的难点在于数据的一致性,redis和mysql的数据一致
性。数据一致性负载均衡解决,负载均衡使用的一致性哈希,一致性哈希就是将整个哈希
看做一个圆环,服务器对2^32取余放置在圆环上,将存储的数据也取余放在圆环,存储
在顺时针遇到的第一个服务器中,这样的话防止了服务器崩溃导致的数据重新存储在服务
器的问题。redis和Mysql的数据一致性使用的先删除缓存在更新数据库。
3、java中怎么创建 一个线程?
1.继承Thread类创建线程
2.实现Runnable接口创建线程类
3.实现callable创建线程
4、run()方法和start()方法的区别
新建线程的时候进入New(新建)状态,然后调用start后会进入可执行状态,start是Thread类的默
认执行入口,用start启动线程,实现了真正的多线程运行,等线程分配到时间片以后就可以进入运
行状态,调用run()方法。而直接调用run方法的话,他仅仅是类的一个普通方法,并且在主线程中
执行。
5、接口和抽象类的区别
1.抽象类方法只声明,不实现。
2.抽象类不可以被实例化
3.抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,则一定是抽象
类
4.具体派生类必须覆盖基类的抽象方法。
5.抽象派生类可以覆盖基类的抽象方法,也可以不覆盖。但是不覆盖,其具体派生类也必
须覆盖。
区别:
1、抽象类可以有构造方法,接口中不能有构造方法
2、抽象类中可以有普通成员变量,接口中没有普通成员变量。
3、抽象类可以包含静态方法,接口不能包含静态方法
4、接口可以被多继承,但是一个类只能继承一个抽象类
5、如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法,而不必实现,而在抽象类的子类中实现接口方法。
6、怎么实现多线程同步?
1.同步方法:使用synchronized关键字来修饰方法。由于每一个java的对象都有一个
内置锁,当用这个关键字来修饰方法的时候,内置锁会保护整个方法,在调用该方法前,
需要获得内置锁,否则会被堵塞。
2.同步代码块:用synchronized关键字修饰代码块。被该关键字修饰的代码块都会自动
被加上内置锁,从而实现同步。
3.使用volatile实现线程同步:volatile关键字为变量的访问提供了一种免锁机制,
使用volatile修饰相当于告诉虚拟机该域可能会被其他线程中断,所以每次使用该域都
会重新计算,而不是使用寄存器中的值。但他不会提供原子性的操作,也不能来修饰
final类型的变量。
7、synchronized具体怎么用?能给什么对象上锁?
给方法加锁,给代码块加锁,给实例方法加锁。
1、synchronized void sort();和synchronized(this)锁住的是实例对象
2、synchronized static void sort();和synchronized(xxx.class)锁住的是
类对象。
8、多线程中锁的种类
1.可重入锁:synchronized和reentrantLock
2.可中断锁Lock
3.公平锁
4.读写锁
9、http中get与post的区别
get和post是TCP的两种连接。get将参数包含在url而post通过request body传递参
数。get相对post会不安全,因为暴露在了用户视野下。而且get请求会产生一个TCP数
据包,而post会产生两个。对于GET请求,浏览器会将http header 和data一起发出
去,然后服务器响应200,。而post,服务器会先发送header服务器响应100
continue,浏览器再防data,服务器响应200OK。post相对会花费多一点的事件,但
是并不是所有的post都会传两次包,比如火狐就不是。而且网络条件好的时候,一个包
和两个包的影响并不大,在网络条件差的时候,两次包的TCP验证数据包的完整性上有很大优点。
10、http状态码有哪几种?
11、在浏览器中输入一个网址,浏览器的处理过程,涉及哪些层,用了哪些协议?
1.域名解析
2.与服务器建立tcp连接
3.发起http请求
4.服务器响应http请求
5.浏览器得到服务器的响应信息后解析信息,并渲染页面
6.断开连接
http->tcp/udp->ip->arp(根据IP地址获得物理地址)->数据链路层分装成帧->物理
层透明传输比特流->接收端接收,层层上传到应用端,服务器做出响应,并按照之前的路
线传回客户端,断开tcp连接。
12、写代码:输出一个数组中某元素出现的次数超过数组长度一半的元素,没有则输出null。写完有一点小细节有问题,面试官会带着你一步步改
出现的数字,比其他数字出现的次数的和还要大。因此遍历数组保存两个值,一个是当前数字,一个
是这个数字出现的次数,如果数组的下一项出现的数据和此数相同,则time++,不相同就time--。
如果time==0那么则保存下一个数字。
//1,2,3,2,2,2,5,4
public int More(int[] array){
int length = array.length;
int result = array[0];
int time = 1;
for(int i=1;i<length;i++){
if(times==0){
result = array[i];
times = 1;
}
else if(array[i]==result){
times ++;
}
else if(array[i]!=result){
times --;
}
}
times = 0;
for(int i=0;i<length;i++){
if(array[i]==result){
times++;
}
}
if(times>length/2){
return result;
}
else{
return 0;
}
}
1字符串反转
栈实现
public String reverse(){
if(str==null||str.length()==0){
retutn str;
}
Stack<Character> strStack = new Stack<Character>();
char[] chArray = str.toCharArray();
for(Character ch:chArray){
strScack.push(ch);
}
int len = str.length();
for(int i=0;i<len;i++){
chArray[i] = strStack.pop();
}
return new String(chArray);
}
2删除某个链表倒数N个节点
ListNode remove(ListNOde head,int n ){
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
while(fast!=null&&n>-1){
fast = fast.next;
n--;
}
while(fast!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
3链表有没有环?
快慢指针:一个快指针,每次走两步。一个慢指针,每次走一步。
如果快指针和慢指针能够相遇,就证明有环。但是如果链表够长,而环足够小,快指针永远追不上满指针,所以这个方法仅仅适合链表尾部问题,也就是单链表环问题。
public boolean hasycle(ListNode head){
ListNode slow,fast;
slow = fast = head;
while(fast!=null&&fast.next!=null){
slow = slow.next;
fast = fast.next.next;
if(fast==slow)
return true;
}
return false;
}
//碰撞点
public Node firstCircleNode(){
if(!this.hascle()) retrun null;
Node fast = head.next.next;
Node slow = head.next;
while(fast!=slow){
fast = fast.next.next;
slow = slow.next;
}
Node p = head;
while(p!=slow){
p = p.next;
slow = slow.next;
}
return p;
}
链表相交。
public ListNode getNode(ListNode headA,ListNode headB){
if(headA==null||headB==null) return null;
ListNode a = headA;
listNOde b = headB;
while(a!=b){
a = a==null?headB:a.next;
b = b==null?headA:b.next;
}
return a;
}
5.进线程通信方式
1.管道:通常是半双工的。只能用于具有亲缘关系线程之间的通信
2.命名管道:可以无关线程之间交换数据,清除数据,先进先出
3.消息队列:随机查询,不一定是先进先出的次序读取。面向记录的,其中消息具有特定的格式以及特定的优先级。
4.信号量,是一个计数器,用于实现进程间互斥和同步。
Base:武汉
2Hashmap如何实现线程安全,concurrentHashmap原理
1.使用Collections.synchronizedMap();创建一个新的map。
2.HashTable
3.ConcurrentHashMap
4synchronized和reentrantlock的区别,当都被interrupt时,有什么区别
synchronized不能被interrypt但是reentrantLock提供多样化同步,比如时间限制的同步,可以被interrupt.
5jvm内存模型,类的加载过程
JMM java内存模型,是一种规范,定义了jvm内存模型,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。
JMM管理程序计数器,方法区(类信息,常量),本地方法栈(和java虚拟机栈类似,对应的native方法),java虚拟机栈(方法执行会创建一个栈帧用来存储局部变量表,操作栈)一个方法的调用过程,对应着入栈和出栈,堆(存放实例变量)这个五大数据区。
JMM将线程堆栈和堆之间内存分开。
6如何确定内存泄露的位置
内存泄露指的是出现了无效的引用,导致本来被GC的对象没有被回收掉。
8手写单模式,写了懒汉式和双重检验,问了双双重检验为什么要这么写,为什么锁住了还要加null判断
当单例模式想要同步的时候,直接使用synchronized(Sington.class)会导致效率低,因为同步只有在第一次被调用的时才需要。所以使用双重锁,第一个判断null是为了提高性能,如果第一个判断为空,也有可能会有几个线程同时进入同步块if的可能,所以需要加同步锁判断。
而volatile是因为JVM会将指令重排,而volatile可以防止指令重排。
public class Singleton{
private volatile static Singleton singltton;
private Singleton(){}
public static Singleton getSingleton(){
if(singleton==null){
synchronized(Singleton.class){
if(singleton==null){
singleton = new Singleton();
}
}
}
return singleton
}
}
9不同排序算法的稳定性和空间复杂度
1.冒泡 稳定 O(n*n)
2.快排 不稳定 O(nlogn)
3.归并 稳定 O(nlogn)
4.选择 不稳定 O(n*n)
1.第一题求两个字符串最长公共子序列长度,硬做全ac没啥问题。
3.求一个数组里和最大的子序列。和为sum的组合个数,我一开始用的dfs,过了50%
4.让写一个字符串,在字符相同处做分割。没做出来
redis介绍
写一个模板模式
多态:
public abstract class DodishTemplate {
/**
* 具体的整个过程
*/
protected void dodish(){
this.preparation();
this.doing();
this.carriedDishes();
}
/**
* 备料
*/
public abstract void preparation();
/**
* 做菜
*/
public abstract void doing();
/**
* 上菜
*/
public abstract void carriedDishes ();
}
/**
* 西红柿炒蛋
* @author aries
*/
public class EggsWithTomato extends DodishTemplate{
@Override
public void preparation() {
System.out.println("洗并切西红柿,打鸡蛋。");
}
@Override
public void doing() {
System.out.println("鸡蛋倒入锅里,然后倒入西红柿一起炒。");
}
@Override
public void carriedDishes() {
System.out.println("将炒好的西红寺鸡蛋装入碟子里,端给客人吃。");
}
}
/**
* 红烧肉
* @author aries
*
*/
public class Bouilli extends DodishTemplate{
@Override
public void preparation() {
System.out.println("切猪肉和土豆。");
}
@Override
public void doing() {
System.out.println("将切好的猪肉倒入锅中炒一会然后倒入土豆连炒带炖。");
}
@Override
public void carriedDishes() {
System.out.println("将做好的红烧肉盛进碗里端给客人吃。");
}
}
public class App {
public static void main(String[] args) {
DodishTemplate eggsWithTomato = new EggsWithTomato();
eggsWithTomato.dodish();
System.out.println("-----------------------------");
DodishTemplate bouilli = new Bouilli();
bouilli.dodish();
}
}
spring中autowired resource区别
@Resource:自动注入,默认按名称装配
@autowired:默认按类型装备
8杯水,如何最少老鼠找出一杯有毒的
给瓶子编号0~7,并把编号翻译成二进制串,刚好可以用三位二进制来表示。让三只老鼠分别对应三位二进制,然后形成如下交叉表:
老鼠1 老鼠2 老鼠3
0 = 0 0 0
1 = 0 0 1
2 = 0 1 0
3 = 0 1 1
4 = 1 0 0
5 = 1 0 1
6 = 1 1 0
7 = 1 1 1
其中二进制位为1的地方表示哪只老鼠吃哪瓶药。即:
老鼠1应该喝4,5,6,7号的药;
老鼠2应该喝2,3,6,7号的药;
老鼠3应该喝1,3,5,7号的药。
最后观察的时候,可以根据老鼠死了的情况,0表示没死,1表示死了。
比如三只老鼠死了的情况是(1,0,1)则表示5号药是有毒的。因为只有这种
算法:找出循环链表第一个节点
链表逆转
三面
找出无序无重复数组中的第k小
1.redis用到了哪些接口
2.介绍一下垃圾回收算法,以及项目里是怎么配置的
3.项目里面怎么配置内存分区大小的
6.为什么要分成MVC架构,有什么好处
7.分布式项目中session一致性
1.session复制
多个web-server之间相互同步session,这样每个web-server之间都会包含全
部的session。
2.客户端存储法
服务端存储所有用户的session,内存占用大,可以将session存储到浏览器
cookie中,每个端只要存储一个用户的数据了。
8.手撕代码:链表合并
讲一下类加载
1.加载:将类的class文件读取到内存,并为之创建一个java.lang.Class对
象。
2.链接:当类被加载之后,系统为之生成一个对应的Class对象,接着会进入链
接阶段,链接阶段负责把类的二进制数据合并到JRE中。类加载可分为如下三个
阶段。
2.1验证:用于检验加载的类是否有正确的内部结构。并且和其他类协调一致
2.2准备:为类的静态变量分配内存,并设置默认值
2.3解析:将类的二进制数据中的符号引用替换成直接引用。
3.初始化:为可的静态变量赋予正确的初始值。和准备阶段是不矛盾的。如
private static int a = 10;执行过程为:1.字节码文件被加载到内存后,
先进行验证,然后准备,给a分配内存,因为变量a是static的,所有此时a等于
int类型的默认初始值0,即a=0,然后到解析,到初始化这一步的时候,才将10
赋值给a,此时a=10
Java的NIO,讲一下多路复用
如果有10亿个url,怎么对它去重
6 项目 Mybatis和Mysql有什么关系??MVC讲讲
单链表反转