記一個有意思的面試題 → 線程交替輸出問題

開心一刻

大年初一,一塊兒嗨起來!!!git

  強調一句很重要的內心話:祝你們在 2021 年,健康好運,平安幸福!面試

問題描述

  用兩個線程,一個輸出數字,一個輸出字母,交替輸出 1A2B3C4D...26Zspa

  該如何實現?線程

解決方式

  聽說解決方式有上百種,但有些是脫了褲子放屁,有些是民間偏方,因此不必所有都知道(其實樓主也不知道具體是哪一百多種)code

  掌握經常使用的那幾個就好;爲了方便,咱們就以 1234567 和 ABCDEFG 爲例進行演示blog

  synchronized + wait + notify

  若是咱們對 JUC 不熟的話,那這種方式每每是咱們最容易想到的ip

  這種方式,相信你們都能寫出來,可是這裏留三個問題(面試點)get

  一、線程代碼中, try 中的 notify() 可否與 wait() 交換位置,爲何it

  二、線程代碼中, for 下的 notify() 可否去掉,爲何io

  三、上面的代碼可否保證必定先輸出數字,爲何,如何保證必定先輸出數字

  ReentrantLock + Condition + await + signal

  不少場景下,用 ReentrantLock 能夠替代 synchronized ,而在交叉輸出這個場景中,一樣能夠替代

  這種方式,寫出來應該也不難,一樣留三個問題(面試點)

  一、線程代碼中, for 中的 signal() 可否與 await() 交換位置,爲何

  二、線程代碼中, for 下的 signal() 可否去掉,爲何

  三、上面的代碼可否保證必定先輸出數字,爲何,如何保證必定先輸出數字

  LockSupport + park + unpark

  估計不少人都沒想到這種方式,直接上代碼

  這是目前最優的解決方式,照樣留四個問題(面試點)

  一、 t1.start() 可否與 t2.start() 交換位置,爲何

  二、線程 t1 中的 LockSupport.unpark(t2) 在線程 t2 中的 LockSupport.park() 以前執行會怎麼樣,爲何

  三、上面的代碼可否保證必定先輸出數字,爲何

  四、 LockSupport 的 park 、 unpark 與  Object 的 wait 、 notify 有什麼異同

  CAS

  這種方式可能也比較難想到,直接上代碼

  這種方式也許不太好理解,留四個問題(面試點)加深理解

  一、線程代碼中, while 條件爲何是 !=,而不是 ==

  二、上面的代碼可否保證必定先輸出數字,爲何

  三、CAS 的優缺點是什麼,適用於什麼場景

  CAS + AtomicInteger

  其實就是 CAS 的一個變種,直接上代碼

  CAS + AtomicReference

  也是 CAS 的一個變種,直接上代碼

  TransferQueue

  通常很難想象到這種方式,但倒是頗有趣的一種實現方式

  若是不瞭解 TransferQueue ,那這種方式就想不到;一樣留一個問題(面試點)

  一、上面的代碼可否保證必定先輸出數字,爲何

  BlockingQueue

  通常也比較難想到這種方式,有所瞭解就好

  PipedStream

  效率很低,知道有這麼回事就好

總結

  一、示例代碼地址:juc-demo

  二、須要掌握的實現方式

    synchronized、ReentrantLock、LockSupport、CAS、TransferQueue 這幾種實現方式必須掌握

    其餘的瞭解就好

  三、如何保證必定先輸出數字

    上面介紹的那些方式中,有些是不能保證必定先輸出數字的,而有些是能保證必定先輸出數字的

    不能保證先輸出數字的,能夠用 CountDownLatch 來控制,是一種比較理想的作法

相關文章
相關標籤/搜索