朋熙面试(部分)

一面

  • Spring源码有什么可借鉴之处?Spring bean的生命周期?Spring容器近似是个什么数据结构?A:Spring容器是一个Map类型的数据结构,其中key是Bean的名称,value是Bean的实例。

  • 索引优化应该从哪些方面考虑?Answer by newBing:
    首先应考虑在 where 及 order by涉及的列上建立索引;
    应尽量避免在 where 子句中使用 !=或<> 操作符,否则将引擎放弃使用索引而进行全表扫描;
    索引长度以及区分度;
    联合索引需要考虑索引先后顺序(最左前缀匹配);
    索引覆盖是指,如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到磁盘再找数据(即避免回表)。

  • Reentrantlock公平锁、非公平锁。相关知识:本博----一些AQS相关的知识

  • 为什么不同的隔离级别读到的数据不一样?了解MySQL MVCC的Read View吗?相关知识可参考本博----《高性能Mysql 第三版》笔记中MVCC的部分

  • 数据库如何回滚?A:undo log. Q: 如果你来设计undo log,你怎么做? 参考上个回答中的内容

  • kafka的消息,是按什么算法,决定它被分配到哪个partition的?参考答案1,2
    If a partition is specified in the record, use it 指定了partition,则消息投递到指定的partition
    If no partition is specified but a key is present choose a partition based on a hash of the key 未指定partition,但指定了key, 则基于hash(key)取模选择一个分区
    If no partition or key is present choose a partition in a round-robin fashion 分区编号和key均未指定,则轮询选择,round-robin

二面

  • 两个线程同时对HashMap进行写操作,会有什么线程安全的问题吗?举例说明。后面在聊ConcurrentHashMap在JDK1.8之后锁的变化,我聊到锁粒度变小,面试官问有没有粒度变大的情形,比如扩容时?结合3等文和面试官最后的总结来看,应该是没有
  • synchronized锁升级过程。Q:锁升级的意义?为什么没有锁降级?相关知识:我还是倾向于认为没有锁降级,从https://segmentfault.com/q/1010000020803904来看有过锁降级的提案 JEP draft: Concurrent Monitor Deflation,但是似乎被否了。
  • Monitor。相关知识4朋熙面试(部分)_第1张图片
    通俗来说就是调用了wait()方法的线程就会进入waitset
    朋熙面试(部分)_第2张图片
    上图来自 https://www.artima.com/insidejvm/ed2/threadsynch.html,有时间可看看。
    扩展与类比:接口java.util.concurrent.locks.Condition的注释:

Condition factors out the Object monitormethods (wait, notify and notifyAll) into distinct objects togive the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations.Where a Lock replaces the use of synchronized methodsand statements, a Condition replaces the use of the Object monitor methods.

  • AQS的原理?除了CLH同步队列,没有其它队列吗?参考答案5:条件队列。更准确点应该是Lock的Condition会有条件队列。
    类AbstractQueuedSynchronizer里的static final class Node是CLH同步队列的结点类,从下面Node类的一段注释,以及AQS里用到的ConditionObject类的代码都可以看出,它同时也是条件队列的结点类:

Threads waiting on Conditions use the same nodes, but use an additional link. Conditions only need to link nodes in simple (non-concurrent) linked queues because they are only accessed when exclusively held. Upon await, a node is inserted into a condition queue. Upon signal, the node is transferred to the main queue. A special value of status field is used to mark which queue a node is on.

 public class ConditionObject implements Condition, java.io.Serializable {
        ...
        /** First node of condition queue. */
        private transient Node firstWaiter;
        /** Last node of condition queue. */
        private transient Node lastWaiter;

        ...

        /**
         * Adds a new waiter to wait queue.
         * @return its new wait node
         */
        private Node addConditionWaiter() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node t = lastWaiter;
            // If lastWaiter is cancelled, clean out.
            if (t != null && t.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                t = lastWaiter;
            }

            Node node = new Node(Node.CONDITION);

            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;
            lastWaiter = node;
            return node;
        }

		...
        public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            ...
        }

Condition的条件队列像极了Monitor的Wait Set。区别是Condition更灵活,因为一个Lock可以有多个Condition,也就可以有多条条件队列,但是一个Monitor有且只有一个Wait Set。唯一的疑惑是Condition.await方法是否会删除同步队列里的头节点。从代码和注释里我没有找到删除的证据,但是我倾向于删了,因为这动作事实上会造成该线程阻塞,似乎不应该再留它当头节点。

    • BlockingQueue的offer方法,底层如何实现的?相关知识:ArrayBlockingQueue的源码:一个Lock及它的两个Condition:
    final ReentrantLock lock;

    /** Condition for waiting takes */
    private final Condition notEmpty;

    /** Condition for waiting puts */
    private final Condition notFull;
    ...
    public ArrayBlockingQueue(int capacity, boolean fair) {
	    if (capacity <= 0)
	        throw new IllegalArgumentException();
	    this.items = new Object[capacity];
	    lock = new ReentrantLock(fair);
	    notEmpty = lock.newCondition();
	    notFull =  lock.newCondition();
    }
    • 线程池应该用ArrayBlockingQueue还是LinkedBlockingQueue好?相关知识:LinkedBlockingQueue相对于ArrayBlockingQueue来说,具有更高的吞吐量,因为它实现了更加细粒度的锁操作。LinkedBlockingQueue中的锁是分离的,即生产用的是putLock,消费用的是takeLock。这样可以在高并发情况下减少锁竞争,提高吞吐量。LinkedBlockingQueue缺点在于没有限定长度,有内存溢出风险
  • 一个接口响应慢,可能是哪些原因?网络延迟、数据库负载过高、代码问题、缓存失效、第三方服务故障、被限速等.

  • 有遇到过MQ消息堆积的情况吗

主管面


  1. 本博----《专题四 服务化改造》之《第三章 【补充资料】常见消息中间件应用详解》之《第十节 Kafka》 ↩︎

  2. kafka-partition分配的策略 ↩︎

  3. 深入解析ConcurrentHashMap:感受并发编程智慧 ↩︎

  4. Java并发编程之Monitor工作原理(有图解) ↩︎

  5. AQS之条件队列Condition (更推荐,含实例等)
    AQS同步队列与条件队列的关系 ↩︎

你可能感兴趣的:(面试,java并发,AQS,BlockingQueue,Monitor,Condition,Read,View)