【笔面试真题】Flow++赋乐科技-面试-2022年1月25日

一、概括

涉及JVM的GC、三色标记

并发部分的锁

Java集合中的hashmap、list

kafka中ISR相关

硬件相关-有无DMA

自定义类(代码)

缺陷:锁、list

二、JVM相关内容

1、如何判断什么是垃圾

(1)方法1:有无引用指向-reference count

无法解决循环引用

(2)可达性分析/根可达算法

从根main函数上能找到的对象

2、介绍一下常见的垃圾回收算法

(1)标记-清除算法(Mark-Sweep):碎片化现象

(2)拷贝复制算法(Copying):有用的拷贝到另一半(空闲面),但浪费空间

(3)标记-整理算法(Mark-compact):清除垃圾后,把有用的往前放

(4)分代收集算法:

堆:新生代(Tenured Generation)+老年代

非堆:永久代(Permanet)

新生代回收大量对象,老年代回收少量对象

3、不同的垃圾回收器

Serial Old/Serial

Parallel Old/ParNew/Parallel Scavenge

CMS(Concurrent Mark Sweep)

G1

ZGC

4、描述一下三色标记算法

在Concurrent Mark Sweep,CMS-并发垃圾回收器中

并发(GC+业务线程分别进行)操作存在在的问题:浮动垃圾

如何找到没有引用的对象-三色标记算法

黑、白、灰

存在问题:

(1)业务线程标记已回收对象指向被引用节点(白色),采取Incremental Update

(2)上述并发方式,容易产生漏标,remark再标一遍

三、Java并发-常见的锁

常见的锁分类大致有:排它锁、共享锁、乐观锁、悲观锁、分段锁、自旋锁、公平锁、非公平锁、可重入锁等。

1.公平锁 / 非公平锁:是否按顺序申请锁

2.可重入锁 / 不可重入锁:是否可重复或递归调用,ReentrantLock和synchronized/两次调用lock()不释放导致死锁

3.排他锁 / 共享锁:C.U.T包下的ReeReentrantLock/ReentrantReadWriteLock

4.互斥锁 / 读写锁:访问共享资源前加锁/读时加锁、写时加锁、不加锁(既是共享锁,也是排他锁)

5.乐观锁 / 悲观锁:java.util.concurrent.atomic包下面的原子变量类使用CAS/synchronized和ReentrantLock等独占锁只给一个进程使用

6.分段锁:是一种锁的设计,ConcurrentHashMap就是基于分段锁实现高效并发

7.偏向锁 / 轻量级锁 / 重量级锁:一段同步代码一直被一个线程所访问/锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁/锁为轻量级锁时,另一个线程自旋一定次数时还没有获取到锁,就会进入阻塞

8.自旋锁:CAS是英文单词Compare and Swap(比较并交换),当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环

 四、java集合

1、HashMap

JDK1.7:Entry数组 + 链表

JDK1.8:Node 数组 + 链表/红黑树,转红黑树提高查询效率到O(logN)

2、HashMap是否线程安全,如何保证线程安全

使用 ConcurrentHashMap保证线程安全

或者使用

Collections.synchronizedMap(hashMap),使其实现同步

3、ConcurrentHashMap如何保证线程安全

采用锁分段技术,将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段 segment,而且每个小的片段 segment 上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个片段 segment,然后再在这个片段上面进行插入,而且这里还需要获取 segment 锁

4、HashMap 与 HashTable 的区别

HashTable 基于 Dictionary 类,而 HashMap 是基于 AbstractMap

HashMap 的 key 和 value 都允许为 null,而 Hashtable 的 key 和 value 都不允许为 null

Hashtable 是线程安全的,而 HashMap 不是线程安全的

5、List的subList返回的对象和原始的引用相关吗

不会返回新的list对象

返回原来list的从[fromIndex, toIndex)之间这一部分的视图,实际上,返回的list是靠原来的list支持的。

对原来的list和返回的list做的“非结构性修改”(non-structural changes),都会影响到彼此对方。

如何删除一个list的某个区段:list.subList(from, to).clear();--将元素释放并清空内部属性

6、String的subString

返回一个新的字符串,是原始字符串的子字符串

字符串会存放在堆内存

返回一个新的字符串对象

五、kafka的ISR队列和OSR队列

1、含义

ISR(In-Sync Replicas),副本同步队列。ISR中包括Leader和Follower。如果Leader进程挂掉,会在ISR队列中选择一个服务作为新的Leader。有replica.lag.max.messages(延迟条数)和replica.lag.time.max.ms(延迟时间)两个参数决定一台服务是否可以加入ISR副本队列,在0.10版本移除了replica.lag.max.messages参数,防止服务频繁的进去队列。
任意一个维度超过阈值都会把Follower剔除出ISR,存入OSR(Outof-Sync Replicas)列表,新加入的Follower也会先存放在OSR中。

2、深层次理解

(1)消息组成

LEO:从哪落盘,即表示下一条待写入数据的index【下一条待写入位置】
HW:表示数据从哪消费,HW之前的数据对消费者可见,能够被消费者消费
firstUnstableOffset:第一条未提交数据
lastStableOffset:最后一条已提交数据
LogStartOffset:起始位置
(2)如何通过更新LEO,进行副本同步
leader和follower都有HW,LEO会选择ISR中HW和自身LEO最小的进行写入,LEO落盘后,进行+1
当leader挂掉,变为follower后,follower的HW会覆盖当前节点的HW,会导致数据丢失

六、DMA--延伸到零拷贝机制

“Direct Memory Access(存储器直接访问)。这是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据。整个数据传输操作在一个称为"DMA控制器"的控制下进行的。CPU除了在数据传输开始和结束时做一点处理外(开始和结束时候要做中断处理),在传输过程中CPU可以进行其他的工作(前提是未设置停止CPU访问)。这样,在大部分时间里,CPU和输入输出都处于并行操作。因此,使整个计算机系统的效率大大提高”。

DMA方式中,主存与I/0设备之间有一条数据通路(专用数据总线),则交换信息时无需像中断一样调用中断服务程序,数据不经过CPU,直接通过这条线传输,所以DMA是需要硬件支持的。【使用硬件传输数据】

1、含义

DMA是一种内存访问技术;
可以独立于CPU, 直接读、写系统存储器、外设等

2、使用原因

把比较固定的任务让DMA来做,可以减轻CPU负担,提高系统的效率

DMA具有一般CPU没有的高效操作,提高系统的吞吐率

3、kafka的零拷贝机制

传统的传输方式

零拷贝机制--没有去内存中拷贝数据

无需经过CPU拷贝数据到内存中 

从硬盘直接读到操作系统内核的读缓冲区里面

根据 Socket 的描述符信息,直接从读缓冲区里面,写入到网卡的缓冲区里面

具体实现:-使用NIO机制,实现了直接内存缓冲区的开辟

应用程序通过调用mmap(),将不同的虚拟地址映射到了同一物理地址,即内核缓冲区,使程序在用户态可以直接读取并操作内核空间的数据

使用DMA的方式将磁盘数据读取到内核缓冲区,然后通过内存映射的方式,使用户缓冲区和内核读缓冲区的内存地址为同一内存地址

七、自定义类-list实现栈

import java.util.LinkedList;

/**
 * Created by lili on 15/11/14.
 */
public class MyStack {
    private LinkedList linkedList;

    public MyStack() {
        linkedList = new LinkedList();
    }

    public void push(Object o) {
        linkedList.addFirst(o);
    }

    public Object pop() {
        //删除并返回
        return linkedList.removeFirst();
    }

    public boolean isEmpty() {
        return linkedList.isEmpty();
    }
}

 

posted @ 2022-01-25 20:57  哥们要飞  阅读(200)  评论(0编辑  收藏  举报