摩根斯坦利面試——Java多執行緒
阿新 • • 發佈:2019-02-02
今天上午,參加大摩的面試,自覺失敗,記錄一下過程。
面試官看著簡歷,並沒有就簡歷提問,整個過程都在問java多執行緒的問題。
1. ReentrantLock,作為可重入鎖,怎麼理解“可重入”二字,有沒有不可重複的鎖?
我:獲得物件鎖的執行緒能夠再次獲得物件鎖,訪問物件……被鄙視了,後來想想,應該把遞迴這種場景說下;
2.生產者-消費者模型怎麼實現?
我:使用synchronized或者Lock這些同步方法實現。
面試官就問,為什麼不用一些更高階的封裝呢?
我:可以使用Exchanger類。
面試官:用BlockingQueue也可以,接下來,
3.作為一個介面,它有哪些具體的實現類?如何實現一個BlockingQueue,請實現它?
我:不清楚具體實現(後來查了下,有ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue,DelayQueue,SynchronousQueue,前兩個最常見)。
可以使用List來儲存資料,使用Lock與Condition來保證同步,程式碼如下(最好使用模板),
public class DefinedBlockingQueue { private LinkedList<Integer> queue; private Lock lock; private int max; private Condition empty; private Condition full; public DefinedBlockingQueue(LinkedList<Integer> 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.<strong>signal</strong>(); }