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

问题描述

用两个线程,一个输出数字,一个输出字母,交替输出 1A2B3C4D…26Z


该如何实现?

解决方式

据说解决方式有上百种,但有些是脱了裤子放屁,有些是民间偏方,所以没必要全部都知道(其实楼主也不知道具体是哪一百多种)

掌握常用的那几个就好;为了方便,我们就以1234567和ABCDEFG为例进行演示

synchronized + wait + notify

如果我们对JUC不熟的话,那这种方式往往是我们最容易想到的

这种方式,相信大家都能写出来,但是这里留三个问题(面试点)

1、线程代码中,try中的notify()能否与wait()交换位置,为什么

2、线程代码中,for下的notify()能否去掉,为什么

3、上面的代码能否保证一定先输出数字,为什么,如何保证一定先输出数字

ReentrantLock + Condition + await + signal

很多场景下,用ReentrantLock可以替代synchronized,而在交叉输出这个场景中,同样可以替代

这种方式,写出来应该也不难,同样留三个问题(面试点)

1、线程代码中,for中的signal()能否与await()交换位置,为什么

2、线程代码中,for下的signal()能否去掉,为什么

3、上面的代码能否保证一定先输出数字,为什么,如何保证一定先输出数字

LockSupport + park + unpark

估计很多人都没想到这种方式,直接上代码

这是目前最优的解决方式,照样留四个问题(面试点)

1、t1.start()能否与t2.start()交换位置,为什么

2、线程 t1 中的LockSupport.unpark(t2)在线程 t2 中的LockSupport.park()之前执行会怎么样,为什么

3、上面的代码能否保证一定先输出数字,为什么

4、LockSupport的park、unpark与Object的wait、notify有什么异同

CAS

这种方式可能也比较难想到,直接上代码

这种方式也许不太好理解,留四个问题(面试点)加深理解

1、线程代码中,while条件为什么是 !=,而不是 ==

2、上面的代码能否保证一定先输出数字,为什么

3、CAS 的优缺点是什么,适用于什么场景

CAS + AtomicInteger

其实就是 CAS 的一个变种,直接上代码

CAS + AtomicReference

也是 CAS 的一个变种,直接上代码

TransferQueue

一般很难想象到这种方式,但却是很有趣的一种实现方式

如果不了解TransferQueue,那这种方式就想不到;同样留一个问题(面试点)

1、上面的代码能否保证一定先输出数字,为什么

BlockingQueue

一般也比较难想到这种方式,有所了解就好

PipedStream

效率很低,知道有这么回事就好

总结

1、示例代码地址:juc-demo

2、需要掌握的实现方式

synchronized、ReentrantLock、LockSupport、CAS、TransferQueue 这几种实现方式必须掌握

其他的了解就好

3、如何保证一定先输出数字

上面介绍的那些方式中,有些是不能保证一定先输出数字的,而有些是能保证一定先输出数字的

不能保证先输出数字的,可以用CountDownLatch来控制,是一种比较理想的做法

最后

最近我整理了整套《JAVA核心知识点总结》,说实话 ,作为一名Java程序员,不论你需不需要面试都应该好好看下这份资料。拿到手总是不亏的~我的不少粉丝也因此拿到腾讯字节快手等公司的Offer

Java进阶群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值