面试题:三个线程轮流打印A ,B,C
- 面试介绍说明
- 思考方案
- 代码实现
- Print 打印基类
- APrint 打印字符A 线程
- CPrint 打印字符C 线程
- PrintConstant 常量类
- Str
- Run 启动类
- 测试结果
- 总结
面试介绍说明
当时是2022 年3月 在深圳面试的一家公司。由于疫情比较严重,是电话面试。前面的八股文还比较熟悉,和面试官沟通的还不错。后面聊到多线程,说让实现 三个线程轮流打印 ABC。我当时听,有点懵,之前只是复习了用wait/notify 来实现生产消费者模型。只有两个主体,现在 是三个,瞬间没有了主意,当时也是 和面试官 纠缠了一会,但面试官很较真,他说 他正打开 idea,让我说,他来敲代码。于是 GG…现在又重新学习下多线程,自己突然有了思路,然后就写了下,发现居然没有毛病。特此记录下。
思考方案
还是建立在生产者和消费者模型下。 只是多个了一个主体。执行run 方法的时候,加个判断即可。
流程如下:
代码实现
Print 打印基类
/**
* @author :echo_黄诗
* @description:打印基类
* @date :2023/2/3 17:03
*/
public class Print extends Thread{
protected Str str;
protected Object lock;
public Print(Str str,Object lock) {
this.str = str;
this.lock=lock;
}
}
APrint 打印字符A 线程
/**
* @author :echo_黄诗
* @description:打印字符A 线程
* @date :2023/2/3 16:59
*/
public class APrint extends Print{
public APrint(Str str, Object lock) {
super(str, lock);
}
@Override
public void run() {
//获取锁
synchronized (lock){
//当前线程 状态正常的
while (!Thread.currentThread().isInterrupted()){
if (str.getString().equals(PrintConstant.C)){
System.out.println(PrintConstant.A);
str.setString(PrintConstant.A);
}else {
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
CPrint 打印字符C 线程
/**
* @author :echo_黄诗
* @description:打印字符C 线程
* @date :2023/2/3 17:05
*/
public class CPrint extends Print {
public CPrint(Str str, Object lock) {
super(str, lock);
}
@Override
public void run() {
//获取锁
synchronized (lock){
//当前线程 状态正常的
while (!Thread.currentThread().isInterrupted()){
if (str.getString().equals(PrintConstant.B)){
System.out.println(PrintConstant.C);
str.setString(PrintConstant.C);
}else {
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
PrintConstant 常量类
/**
* @author :echo_黄诗
* @description:常量类
* @date :2023/2/3 18:11
*/
public class PrintConstant {
public static final String A="A";
public static final String B="B";
public static final String C="C";
}
Str
/**
* @author :echo_黄诗
* @description:信号量类
* @date :2023/2/3 17:07
*/
public class Str {
private String string;
public Str(String string) {
this.string = string;
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
Run 启动类
/**
* @author :echo_黄诗
* @description:测试类
* @date :2023/2/3 17:06
*/
public class Run {
public static void main(String[] args) {
Object lock=new Object();
//str 的值可以赋值
Str str=new Str(PrintConstant.C);
APrint aPrint=new APrint(str,lock);
BPrint bPrint=new BPrint(str,lock);
CPrint cPrint=new CPrint(str,lock);
aPrint.start();
bPrint.start();
cPrint.start();
}
}
测试结果
三个线程 的启动顺序没有要求。
总结
目前能用notify/wait 方式实现的功能,用 lock 和condition 应该都可以实现。小伙伴们有兴趣的试着用lock 来实现下。