滴滴java开发面试题_滴滴java开发工程师面试问题解答(第一回)

有位同学写了一个滴滴面试拿offer的经历,据说还面了滴滴的CTO,我就好奇,这CTO面又能是个啥水平呢?对他在文章中提到的部分问题做个解答吧。

原文请见滴滴CTO五轮面试真是太刺激了,Java高级工程师一二三四五面面经(已拿到offer)_a3961401的博客-CSDN博客​blog.csdn.net45c70b6d913fde11316e99670af3b909.png

Q1. Java线程的状态及转换java线程状态转换图,好老了

New Thread:线程新创建的状态

Thread myThread = new MyThreadClass();

Runnable: 可运行状态

Thread myThread = new MyThreadClass();

myThread.start();

start方法创建运行线程所需要的系统资源.

Not Runnable: 不可运行状态

下面几种情况可以让线程进入不可运行状态Someone invokes its sleep method.

Someone invokes its suspend method.

The thread uses its wait method to wait on a condition variable.

The thread is blocking on I/O.

Dead:死亡状态A thread can die in two ways: either from natural causes, or by being killed (stopped). A thread dies naturally when its run method exits normally. For example, the while loop in this method is a finite loop--it will iterate 100 times and then exit

Q2. Java创建线程的方式

Java有三种创建线程的方式:通过实现Runnable接口

extending Thread类

通过Callable和Future创建线程

3. 创建线程池的方式有哪些

主要有下面四种方法创建线程池newCachedThreadPool: 创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程

newFixedThreadPool: 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

newScheduledThreadPool :创建一个定长线程池,支持定时及周期性任务执行

newSingleThreadExecutor: 创建一个单线程化的线程池,它只会唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行

Q3. JUC包下的类,能说多少说多少

JUC指的是关于java.util.concurrent类包下的常用类。JUC类关系图

这个package下主要的类有如下:Executor

ExecutorService:进行异步处理,管理内存队列和调度提交的任务

ScheduledExecutorService:跟ExecutorService类似,但是提供周期性任务

Future

CountDownLatch:JDK5中引入的工具类,阻塞一组线程、直到某些操作完成

CyclicBarrier

Semaphore

ThreadFactory

BlockingQueue

DelayQueue

Locks

Phaser

Q4. ReentranLock与sychronized的区别

具体参考这篇文章Synchronize和ReentrantLock区别​juejin.im

Q5. volitile的内存语义,底层如何实现

对于内存语义,简单的说就是要保证读后写、写后读以及写后写等几种情况的数据一致性。主要方法就是每次写内存时都从线程的共享内存写到主机内存,每次读之前都从主机内存读到线程的共享内存。跟SMP的思想非常类似。

简单的说,底层通过memory barrier来实现不同线程之间的volitile读写。其实了解Linux Kernel变成的同学对这个概念应该并不陌生。Volitile关键字禁止了编译器的代码优化,使特定处理器的编译器针对并发的代码重排被禁止,这种禁止会影响系统的并发性能,但是能保证数据的一致性。也是一种权衡的设计吧。

至于Happend-before原则,可进一步参考这里Volatile的内存语义​www.jianshu.com44b93dde6d82bdfd0663850cfb5dca68.png

Q6. ConcurrentMap源码如何实现

并发Map主要采用了分段技术(一种内部数据结构)来获取针对map的并发访问,原理很简单,把map在内部分成很多段,只有访问对应段的数据时,需要对其加锁。其他时候,多个线程可以并发的访问自己的数据部分。极大的改善了并发性能。

默认是提供32个分段

对于每个键值对,则是存储在一个叫做Map.Entry的结构中,见下图

从这个结构里面有,key-value,hash和next。比较好理解,就不多解释了。

ConcurrentMap定义了一组Map.Entry结构来存储键值对

protected transient Entry[] table;

Q7. Zookeeper用过吗,介绍一下https://zhuanlan.zhihu.com/p/157317221​zhuanlan.zhihu.comzhihu-card-default.svg

请参考上面这篇文档

Q8. LSM-tree应用在那些场景、优缺点

在YCombinator上看到了一篇讲解的文章,推一下Introduction to LSM Trees: May the Logs Be with You​news.ycombinator.com

还有另一篇文章https://medium.com/databasss/on-disk-io-part-3-lsm-trees-8b2da218496f​medium.com

LSM Tree全称是Log Structured Merge Tree,也就是日志结构的归并树。我们知道,最简单的数据库实现就是日志化的数据库实现,只在最后做append操作,不考虑查找和in-place的修改。

一个LSM Tree一般由两层或多层的树形数据结构组成,树形结构一般两种形态,C0和C1。

C0被叫做内存表,是完全驻留在内存中的。一般由平衡二叉树AVL实现,将排好序列K-V对都存储在内存中,插入和删除也在这一层完成。

C1一般体积会大很多,所以都存储在磁盘中。C1中包含很多不可修改的日志分段以及对应的hash索引。C1一般使用SSTable实现。

那么SSTables又是个啥?它跟LSM Tree又是如何结合的呢?

我们知道,日志型数据库是为了适应大规模的并发写入场景,这种设计让写入的效率非常高。但是随着写入的日志增大,怎么样更好的管理写入的文件呢?自然的,我们想到了分段(segment)。这就是SSTables派上用场的地方了,它的全名是“String Sorted Tables”,也就是"排序字符串表"。

SSTables主要作用是在不可修改的日志分段中、按照字符串排序顺序来存储K-V对。

它有两个优点:在全数据hash索引不存在的情况下,查找变得非常高效。

Range查询变得可能。Elastic Search中Range String Query时,就用了SSTables。

当内存中的C0结构大小超过阈值时,它就被刷入到磁盘上,并按照SSTable的形态作为一个新段存储起来。

向LSM Tree中插入数据:当写入发生时,数据首先被写入到内存中的memtable中.

当memtable大小超过阈值时,数据被刷写到磁盘.

因为memtable已经有序,创建新的SSTable分段非常高效.

旧的分段会周期性的合并以减少磁盘占用,同时减少分段数据的数量。

从LSM Tree中读入数据:首先在memtable中查找key.

如果没有找到,然后使用hash索引在一个或者多个分段中查找.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值