记一个有意思的面试题 → 线程交替输出问题

开心一刻

大年初一,一块儿嗨起来!!!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 来控制,是一种比较理想的作法

相关文章
相关标签/搜索