阿里-面经1

用三个线程交替打印出ABCABC

用上SingleThreadPoolExecutor,也就是单例线程池,代码如下:

 

第二种方式,join,抢占时间片,但是不推荐使用,繁琐,看起来没有使用线程池优雅:

第三种方式:Semaphore

 

 

什么时候应该进行垃圾回收?

分两种,第一种是新生代的eden区满了,会触发新生代GC,另一种当对象大于老年代的最大连续内存时,会触发老年代GC

 

synchronized了解吗?哪里会出现?

了解,synchronized也就是一种悲观锁,如果要进行线程间的变量共享时可能会用到它

 

线程和进程的区别?

进程是操作系统调度的最小单元,线程是cpu调度的基本单元,不同进程有不同的内存空间,多个线程共享一个内存空间,一个进程可以有多个线程。线程就是轻量级进程

 

二叉查找树的时间复杂度?

Logn

 

什么时候会内存溢出?

没有被回收的对象太多,内存中加载的数据量过于庞大,启动参数设置内存值设置得太小

 

Hashmap再扩容比较耗时怎么办?

预设hashMap的初始容量

 

说说innodb和myisam的区别?为什么你不选myisam?

InnoDB支持事务,myisam不支持事务,InnoDB支持行级锁,而myisam只支持表锁,InnoDB支持外键,myisam不支持外键。因为我需要经常频繁的操作数据库,假如是用myisAm的话,那么是表锁会影响效率

 

谈谈事务的隔离级别?

未提交读,提交读,可重复读,可串行化

 

建索引时注意哪些问题?

首先要考虑建不建索引,要根据数据的多少来判断,第二是使用频率很低的最好就不要建立索引了,因为索引也是有代价的,可能会得不偿失。

 

红黑树,B树,B+树为什么数据库索引索引用B+树?

因为B+树的磁盘IO代价更低,并且B+树只有叶子节点存储索引,索引每次查找索引都会到达叶子结点,这样的话更加地稳定,并且叶子结点形成链表更利于范围查找

 

数据库锁有哪几种颗粒度?

表级锁,行级锁,页级锁

 

redis了解吗?谈谈redis的认识和5种数据类型

redis是一种分布式缓存,是用C实现的,5种数据类型是string,list,set,zset,hash

 

类加载器,双亲委派模型?

类加载过程中有一步是通过类的全限定名找到对应的二进制字节流,jvm虚拟机设计团队将这一步给独立出来可以让我们来实现,而实现这个过程的代码就是类加载器

双亲委派模型就是类加载器要加载类时要先去找启动类加载器,假如启动类加载器能够加载就加载,不行再子类加载器加载。双亲委派模型保证了一个class不会被重复加载,并且能够保证核心class不会被篡改

 

HashMap的扩容机制,冲突解决?

HashMap有一个负载因子,默认为75%,假如容量超过了这个数,就会进行自动扩容,也就是再哈希,扩容是默认扩容一倍的,假如插入的key的hashcode相同,则会到同一个bucket,不过如果碰到这种情况就会在链表的下一个节点进行插入。这就解决了哈希冲突

 

ArrayList和LinkedList的区别?

ArrayList的底层是动态数组,正因为这个原因,所以ArrayList的查询速度更快,但是如果是删除一个元素则会慢,其实这都是数组的因素。而LinkedList的底层是一个链表,所以它有链表的优点,也就是插入或删除一个元素更快,但是查询会慢一些。

 

HashTable和ConcurrentHashMap?

这两个都是线程安全的,不过hashTable没有ConcurrentHashMap好用,因为hashTable是直接锁住了整张表,所以性能会受到很大影响,而ConcurrentHashmap用的是CAS加synchronized来实现的,更加地快,所以现在一般都选concurrentHashMap了

 

线程ThreadLocal?

ThreadLocal主要是为了避免变量在线程间共享的,它能够将某个值和某个线程关联起来,提供了get和set方法,这些方法为每个使用该变量的线程保有一份独立的副本。假如某个频繁执行的操作需要一个临时对象,我们就可以把它放在ThreadLocal中,这就避免了每次执行时重新分配临时对象

 

内存回收机制,垃圾回收器?

内存回收机制是程序计数器或者可达性分析算法,不过现在一般都是可达性分析算法,也就是Root会和存活的对象关联,假如这条关联没了,那么对象就该被回收了,垃圾回收器主要有serial,parNew,parallel Scavenge,serial old ,cms,parallel old。

 

原子类如何实现原子操作的?

通过CAS来实现的

 

什么是死锁?如何避免死锁?

多个线程互相持有对方需要的资源,就会导致线程都处于等待状态,就会形成死锁。只要破坏死锁的四个条件中的一个就行了。也就是互斥条件,请求与保持条件,不可剥夺条件,循环等待这4个条件中的一个就行了

具有相同的加锁顺序,使用定时锁,使用死锁检测

 

给定整整数n,设计两个线程,A只打印奇数,B只打印偶数,打印顺序1——n?

 

或者这样:

 

 

 

dubbo与springcloud的区别?

dubbo采用的是rpc通信,springcloud采用的是restful风格

 

docker与虚拟机的区别?

docker启动非常快,是秒级别的,虚拟机是分钟级别的

docker更加的轻量级,镜像大小以M为单位,而虚拟机以G为单位

docker占用资源少,性能基本接近物理机。虚拟机性能就没有这么好了

docker只进行了进程级隔离,所以隔离性与稳定性不如虚拟机

 

string的几种拼接方式,和StringBuilder的底层的区别?

1.用+号   2。concat

string和StringBuilder的低底区别是:string的对象不能改变,所有进行的字符串拼接实际上是在内存中新建一个对象,而StringBuilder可以改变,进行拼接时是在原对象上进行的

 

线程池?

了解,线程池可以避免重复的创建和销毁线程,所以降低了资源消耗,提高了响应速度,还提高了线程的可管理性,工作原理就是当一个任务到达时,会先在核心线程池里创建线程,核心线程满了后会去工作队列,工作队列也满了话会创建非核心线程,如果达到了最大线程数量,则会调用拒绝策略

 

tcp三次握手?

第一次握手:客户端设置syn为1,初始序号为x,然后将tcp包发送给服务端

第二次握手:服务端接受到后,会设置自己的syn为1,并把ack设置为x+1,自己的序号设置为y,然后发送给客户端

第三次握手:客户端收到服务端的ack后,会设置自己的ack为y+1,syn为0,序号为z,然后发送包给服务端

三次握手完成,连接成功

 

为什么是三次而不是两次或者4次?

假如是三次的话,那么当服务端发送ack给客户端后,服务端就认为连接已经成功,但是假如客户端没有收到这个ack的话,那么客户端就不会发送请求给服务端,但是服务端一直等待,假如这种连接特别多,那么服务端会崩掉。为什么不是4次呢?因为3次就够了,4次浪费资源

 

 

java内存结构,堆内存划分?

分为方法区,堆,本地方法栈,虚拟机栈,程序计数器。  堆划分为新生代和老年代

 

互斥锁ReentrantLock?

了解,ReentrantLock也是一种锁,不过功能比synchronized更强大, 能够显示地获取和释放锁,可中断的获取锁,设置锁超时时间,它也是一种可重入锁,并且还支持公平性和非公平性。不过我们还是仅在synchronized不能达到要求时才采用ReentrantLock锁

 

乐观锁与悲观锁?

乐观锁就是总是假设的是最好的情况,在读数据的时候不会加锁,只是在更新数据时会检查是否有其他线程修改了数据,这个时候加的是行级锁

悲观锁总是假设的最坏的情况,即读取和修改的时候都会加锁

乐观锁的实现:CAS,原子类,数据库版本号,时间戳        悲观锁:synchronized,ReentrantLock等

 

平衡二叉树与二叉排序树的概念?

二叉排序树也称作二叉查找树,左子树的节点都小于根节点,右子树的节点都大于根节点,左右子树也是二叉排序树

二叉平衡树左右子树的高度差不能超过1,并且左右子也是平衡二叉树

 

java的类加载机制

首先会通过类的全限定名找到对应的二进制字节流,然后将字节流中的静态存储结构转换为动态运行结构,然后生成一个class文件作文方法的入口

 

手写单例模式?

两个栈实现一个队列?

 

 

concurrentHashMap的底层原理?

concurrentHashMap的数据结构是(数组+链表+红黑树)

Node的数据结构简单,是一个链表,但是只允许查找,不允许修改

TreeNode继承自Node,数据结构是二叉树,用于红黑树中存储结构

concurrentHashMap的初始化是空实现,初始化操作是在put操作中实现的

concurrentHashMap的put操作:1.如果没有初始化就调用initTable()方法进行初始化

                                                    2.如果没有hash冲突则直接CAS插入

                                                    3.如果正在进行扩容,那么先进行扩容操作

                                                    4.如果存在hash冲突,那么加锁来保证的线程安全(两种情况:一种是链表直接遍历到尾段进行插入,一种是按照红黑树的结构进行插入)

                                                     5.如果链表的数量大于8,会先转换成红黑树,break后再一次进入循环

                                                     6.如果调用成功就调用addCount()方法统计size,并且检查是否需要扩容

put过程的总结:并发处理时使用的是乐观锁,当有冲突时才进行并发处理

concurrentHashMap的get操作: 1.计算hash值,定位到该table索引的位置,如果首节点符合就直接返回

                                                    3.如果不符合的话,继续向下遍历节点,匹配就返回,否则继续遍历直到遍历到底还是不符合的话就返回null

 

为什么使用synchronized来代替ReentrantLock?

因为粒度降低了,在低粒度的情况下,synchronized的性能并不比ReentrantLock低

2.jvm的开发团队从没有放弃过synchronized,基于jvm的synchronized的优化空间更大

3.大量的数据操作下,ReentrantLock的内存开销更大

 

 

对java代理的理解?

根据表现的形式不同,代理分为静态代理和动态代理,静态代理的代理关系是在编译期就确定的,适用于代理类较少的情况,而动态代理是在运行时确定的。

静态代理的缺点是代理对象的接口只服务于一种类型的对象,如果要代理的方法很多,那么要为每一种方法都进行代理,如果接口增加了一个方法,除了所有实现类都要实现这个方法外,所有的代理类也要实现,增加了代码维护的复杂度

动态代理的优点:所有方法都被转移到一个集中的方法中进行处理

 

 

动态代理的实现方式和区别?

实现方式分为jdk动态代理和CGLLIB动态代理

jdk动态代理要求被代理类至少实现一个接口

CGLIB动态代理要求该类不能被final修饰

jdk动态代理只能对实现了接口的类生成代理,不能针对类

CGLIB动态代理针对的是类,覆盖其中的方法

 

jvm常用命令行调优工具?

jps:负责查看java进程

jinfo:负责查看jvm参数和动态修改jvm参数的命令

jstat:查看jvm运行时的状态信息,包括内存状态和垃圾回收

jstack:查看jvm线程快照(对栈堆进行追踪)

jmap:生成堆dump文件(对内存生成快照)

 

 

redis缓存击穿和缓存雪崩?

缓存击穿:就是重复多次对一个缓存中不存在的数据进行访问,这样的话每次都会去数据库中查找,相当于redis失效了

缓存雪崩:在某一时刻大量的缓存失效,导致大量的请求都直接去到数据库

怎么解决缓存击穿:即使数据库中没有这个值,也设置一个值为null的缓存,不过这个缓存的过期时间设置短一点

怎么解决缓存雪崩:加上锁或者用队列将访问变为串行访问,降低数据库的压力。为缓存设置随机的过期时间。建立缓存备份,也就是A,B缓存,A有过期时间,B没有,先去A查询,查询不到则去B读,然后A,B同时更新

 

jvm回收算法的优缺点

标记清除算法:1.优点:简单

                          2.缺点:垃圾回收后内存变得不连续,造成很大零散的内存空间,创建的大对象可能会不够空间存储

 

复制算法:       1.优点:GC后的内存空间是连续的

                        2.缺点:由于分出了Survivor2不存放对象,真正存放新对象的内存区域变少

 

标记-整理算法 1.优点:避免了标记清除算法和复制算法的缺点

                        2.缺点:效率低

 

老年代用的标记整理算法,新生代用的复制算法,注意,cms使用的是标记清除算法

 

 

数据库B+树索引的建立过程?

数据库按照页从磁盘读       数据在一页中是通过单链表的形式按大小顺序连接的,为了在一页中进行快速的查找,会在页中建立页目录,也就是建立了一个索引,当数据多了一页放不下,就会有更多的页,然后会专门有一页是给存数据的页建立B+索引

 

 

什么是redis?

redis本质上是一个key-value类型的内存数据库,整个数据库是在内存中进行操作的,因为是内存操作,所以性能非常高,并且还能够保存多种数据结构,单个value的最大限制是1GB,List可以做双向链表,以此实现一个轻量级的高性能消息队列服务,缺点是数据库容量会受到物理内存的限制,不能用作海量数据的高性能读写,一个字符串类型的值最大存储512M

 

为什么redis把数据放到内存中?

为什么达到最快的读写速度,如果不放在内存中,磁盘I/O会严重影响redis的性能

 

redis集群会有写操作丢失吗?为什么?

redis不能保证数据的强一致性,因为实际情况下可能会丢失写操作

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值