一、你知道阻塞队列BlockingQueue不?介绍下常见的阻塞队列
回答
BlockingQueue: j.u.c包下的提供了线程安全的队列访问的接口,并发包下很多高级同步类的实现都是基 于阻塞队列实现的
1、当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满
2、从阻塞队列读数据时,如果队列为空,线程将会阻塞等待直到队列里面是非空的时候
常见的阻塞队列
ArrayBlockingQueue:
基于数组实现的一个阻塞队列,需要指定容量大小,FIFO先进先出顺序
LinkedBlockingQueue:
基于链表实现的一个阻塞队列,如果不指定容量大小,默认 Integer.MAX_VALUE, FIFO先进先 出顺序
PriorityBlockingQueue:
一个支持优先级的无界阻塞队列,默认情况下元素采用自然顺序升序排序,也可以自定义排序实现 java.lang.Comparable接口
DelayQueue:
延迟队列,在指定时间才能获取队列元素的功能,队列头元素是最接近过期的元素,里面的对象必 须实现 java.util.concurrent.Delayed 接口并实现CompareTo和getDelay方法
二、说下你知道的调度算法,比如进程间的调度
回答
先来先服务调度算法:
按照作业/进程到达的先后顺序进行调度 ,即:优先考虑在系统中等待时间最长的作业
排在长进程后的短进程的等待时间长,不利于短作业/进程
短作业优先调度算法:
短进程/作业(要求服务时间最短)在实际情况中占有很大比例,为了使得它们优先执行
对长作业不友好
高响应比优先调度算法:
在每次调度时,先计算各个作业的优先权:优先权=响应比=(等待时间+要求服务时间)/要求服务时间,
因为等待时间与服务时间之和就是系统对该作业的响应时间,所以 优先权=响应比=响应时间/要求服务 时间,选 择优先权高的进行服务需要计算优先权信息,增加了系统的开销
时间片轮转调度算法:
轮流的为各个进程服务,让每个进程在一定时间间隔内都可以得到响应
由于高频率的进程切换,会增加了开销,且不区分任务的紧急程度
优先级调度算法:
根据任务的紧急程度进行调度,高优先级的先处理,低优先级的慢处理
如果高优先级任务很多且持续产生,那低优先级的就可能很慢才被处理
三、网盘静态资源下载限速实现原理
回答
(一)下载限速实现原理
1、目的:限制下载速度
2、常用的是漏桶原理和令牌桶原理
(二)什么是漏桶算法
备注:如果是请求限流,请求先进入到漏桶里,漏桶以固定的速度出水,也就是处理请求,当水加的过快也就是请求过多,桶就会直接溢出,也就是请求被丢弃拒绝了,所以漏桶算法能强行限制数据的传输速率或请求数
(三)什么是令牌桶算法
备注:只要突发并发量不高于桶里面存储的令牌数据,就可以充分利用好机器网络资源。如果桶内令牌数量小于被消耗的量,则产生的令牌的速度就是均匀处理请求的速度
四、线程池不允许使用 Executors 去创建,要通过 ThreadPoolExecutor的方式原因?
回答
Executors创建的线程池底层也是调用 ThreadPoolExecutor,只不过使用不同的参数、队列、拒绝策略 等,如果使用不当,会造成资源耗尽问题;
直接使用ThreadPoolExecutor让使用者更加清楚线程池允许规则,常见参数的使用,避免风险
常见的线程池问题:
newFixedThreadPool和newSingleThreadExecutor:
队列使用LinkedBlockingQueue,队列长度为 Integer.MAX_VALUE,可能造成堆积,导致OOM
newScheduledThreadPool和newCachedThreadPool:
线程池里面允许最大的线程数是Integer.MAX_VALUE,可能会创建过多线程,导致OOM
五、线上消息队列故障了,消息堆积了几千万条,怎样快速处理
(一)线上故障了,怎么处理
1、消息堆积了
10
小时,有几千万条消息待处理,现在怎么办
?
2、修复
consumer,
然后慢慢消费?也需要几小时才可以消费完成,新的消息怎么办?
核心思想:紧急临时扩容,更快的速度去消费数据
- 修复Consumer不消费问题,使其恢复正常消费,根据业务需要看是否要暂停
- 临时topic队列扩容,并提高消费者能力,但是如果增加Consumer数量,但是堆积的topic里面的 message queue数量固定,过多的consumer不能分配到message queue
- 编写临时处理分发程序,从旧topic快速读取到临时新topic中,新topic的queue数量扩容多倍,然后再 启动更多consumer进行在临时新的topic里消费
- 直到堆积的消息处理完成,再还原到正常的机器数量