1. 程式人生 > >摩根斯坦利面試——Java多執行緒

摩根斯坦利面試——Java多執行緒

今天上午,參加大摩的面試,自覺失敗,記錄一下過程。

面試官看著簡歷,並沒有就簡歷提問,整個過程都在問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>();
    }