摩根斯坦利面试——Java多线程

2019-04-14 18:09发布

今天上午,参加大摩的面试,自觉失败,记录一下过程。 面试官看着简历,并没有就简历提问,整个过程都在问java多线程的问题。 1. ReentrantLock,作为可重入锁,怎么理解“可重入”二字,有没有不可重复的锁? 我:获得对象锁的线程能够再次获得对象锁,访问对象……被鄙视了,后来想想,应该把递归这种场景说下; 2.生产者-消费者模型怎么实现? 我:使用synchronized或者Lock这些同步方法实现。 面试官就问,为什么不用一些更高级的封装呢? 我:可以使用Exchanger类。 面试官:用BlockingQueue也可以,接下来, 3.作为一个接口,它有哪些具体的实现类?如何实现一个BlockingQueue,请实现它? 我:不清楚具体实现(后来查了下,有ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue,DelayQueue,SynchronousQueue,前两个最常见)。 可以使用List来存储数据,使用Lock与Condition来保证同步,代码如下(最好使用模板), public class DefinedBlockingQueue { private LinkedList queue; private Lock lock; private int max; private Condition empty; private Condition full; public DefinedBlockingQueue(LinkedList queue, int max) { this.queue = queue; this.max = max; lock = new ReentrantLock(); full = lock.newCondition(); empty = lock.newCondition(); } public Integer take() { lock.lock(); Integer t = null; try { while (queue.isEmpty()) { full.await(); } t = queue.poll(); empty.signalAll(); return t; } catch (InterruptedException e) { // e应该做处理 } finally { lock.unlock(); } return t; } public void put(Integer t) { lock.lock(); try { while (queue.size() == max) { empty.await(); } queue.add(t); full.signalAll(); } catch (InterruptedException e) { // e应该做处理 } finally { lock.unlock(); } } }
4. 为什么使用Condition和Lock而不是synchronized和wait()来实现BlockingQueue()? 我:前者具有更好的特性,比如tryLock、读写锁等。 后来我又查了资料,补充: Lock接口支持更灵活的同步代码块结构:使用synchronized关键字时,只能在同一个synchronized块结构中获取和释放控制。 Lock接口允许实现更复杂的临界区结构(控制的获取和释放不出现在同一个块结构中),比如ArrayBlockingQueue类的 void removeAt(int i) { final Object[] items = this.items; // if removing front item, just advance if (i == takeIndex) { items[takeIndex] = null; takeIndex = inc(takeIndex); } else { // slide over all others up through putIndex. for (;;) { int nexti = inc(i); if (nexti != putIndex) { items[i] = items[nexti]; i = nexti; } else { items[i] = null; putIndex = i; break; } } } --count; notFull.signal(); }