当前位置:网站首页>面试题:用程序实现两个线程交替打印 0~100 的奇偶数
面试题:用程序实现两个线程交替打印 0~100 的奇偶数
2022-04-22 02:07:00 【晨xi的光】
面试场景
面试官:Java多线程了解吗?你给我写一下,起两个线程交替打印0~100的奇偶数。
小黄:啊?
面试官:就是有两个线程,一个线程打印奇数另一个打印偶数,它们交替输出,类似这样。
偶线程:0
奇线程:1
偶线程:2
……
奇线程:99
偶线程:100
小黄:啊?
面试官:……嗯。好的。回去等通知吧。
解说
遇到这种突如其来的面试题,有时候会让人无从下手。尽管可能你学习过多线程的知识,但是面试官抛一个问题过来,短时间内可能想不出如何使用这些知识来解决这个具体的问题。其实这个问题考察的知识点并不难,但是如果准备的面试的时候没有看过这道题,一时间还是比较难想出解决方案来的,而且这种题往往是让面试者手写代码。
回到题目上来。首先是两个线程,其次是交替打印。这可以联系到线程之间的通信问题。这时可以想到大致的方向就是加锁,哪个线程拿到锁就打印,然后释放锁让另一个线程获取锁。两个线程轮流拿到锁,实现交替打印的效果。
起两个线程大家都会,加锁也简单,问题是如何让这两个线程轮流拿到锁呢?我们知道,加锁之后线程之前相互竞争锁,而Java默认是不保证锁的公平性的(使用公平锁可能也是一个思路),这就有可能出现同一个线程一直打印而另一个线程一直没有打印的情况。
讨巧的方案
比较容易想的一个方案是,要输出的时候判断一下当前需要输出的数是不是自己要负责打印的值,如果是就输出,不是就直接释放锁。
private int count = 0;
private final Object lock = new Object();
public void turning() {
Thread even = new Thread(() -> {
while (count < 100) {
synchronized (lock) {
// 只处理偶数
if ((count & 1) == 0) {
System.out.println(Thread.currentThread().getName() + ": " + count++);
}
}
}
}, "偶数");
Thread odd = new Thread(() -> {
while (count < 100) {
synchronized (lock) {
// 只处理奇数
if ((count & 1) == 1) {
System.out.println(Thread.currentThread().getName() + ": " + count++);
}
}
}
}, "奇数");
even.start();
odd.start();
}
输出结果如下。
偶数: 0
奇数: 1
偶数: 2
……
奇数: 99
偶数: 100
从输出上看,是实现了题目上的要求,两个线程,一个打印奇数,一个打印偶数,轮流输出。但只是用了一个讨巧的方式避开了线程交替获取锁的需求,明显没有答到面试官想考察的考点上。而且效率较低,如果同一个线程一直抢到锁,而另一个线程一直没有拿到,就会导致线程做很多无谓的空转。那么有没有更好的解决方案,让两个线程严格地交替获取到锁呢?
交替获取锁的方案
private int count = 0;
private final Object lock = new Object();
public void turning() throws InterruptedException {
Thread even = new Thread(() -> {
while (count <= 100) {
synchronized (lock) {
System.out.println("偶数: " + count++);
lock.notifyAll();
try {
// 如果还没有结束,则让出当前的锁并休眠
if (count <= 100) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread odd = new Thread(() -> {
while (count <= 100) {
synchronized (lock) {
System.out.println("奇数: " + count++);
lock.notifyAll();
try {
// 如果还没有结束,则让出当前的锁并休眠
if (count <= 100) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
even.start();
// 确保偶数线程线先获取到锁
Thread.sleep(1);
odd.start();
}
上面为了直观起见,我将两个线程都独立写了出来,其实 Thead 中的代码是相同的,可以抽成一个 Runnable 类。
public void turning() throws InterruptedException {
new Thread(new TurningRunner(), "偶数").start();
// 确保偶数线程线先获取到锁
Thread.sleep(1);
new Thread(new TurningRunner(), "奇数").start();
}
class TurningRunner implements Runnable {
@Override
public void run() {
while (count <= 100) {
// 获取锁
synchronized (lock) {
// 拿到锁就打印
System.out.println(Thread.currentThread().getName() + ": " + count++);
// 唤醒其他线程
lock.notifyAll();
try {
if (count <= 100) {
// 如果任务还没有结束,则让出当前的锁并休眠
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出结果如下。
偶数: 0
奇数: 1
偶数: 2
……
奇数: 99
偶数: 100
这种实现方式的原理就是线程1打印之后唤醒其他线程,然后让出锁,自己进入休眠状态。因为进入了休眠状态就不会与其他线程抢锁,此时只有线程2在获取锁,所以线程2必然会拿到锁。线程2以同样的逻辑执行,唤醒线程1并让出自己持有的锁,自己进入休眠状态。这样来来回回,持续执行直到任务完成。就达到了两个线程交替获取锁的效果了。
至此,本题解决。
扩展
两个线程交替打印的问题解决了,让我们来扩展一下,如果有三个线程,要求让它们交替输出 1、2、3,即。
线程1:1
线程2:2
线程3:3
线程1:1
线程2:2
线程3:3
……
版权声明
本文为[晨xi的光]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_62051288/article/details/124272270
边栏推荐
- [programming question] what is the highest score
- Hj5 binary conversion
- PaddlePaddle basic usage details (four), PaddlePaddle training text classification model
- 14. System information viewing
- Shell基础语法
- 算数四则混合运算表达式求值
- Ezreal -- cut an animation into four action animation successfully -- new unity project (3)
- Leetcode 141, circular linked list
- Android four components interview
- DPI exception of window form dynamically created by WPF
猜你喜欢

Ultimate doll 2.0 | observable practice sharing of cloud native PAAS platform

Profiteering method of blind box project

Leetcode 1572, sum of diagonal elements of matrix

树莓派4B 8G安装日志(3)——编程环境

Raspberry pie 4B 8g installation log (3) - Programming Environment

Why is Nacos so strong

102 page master plan for new generation digital transformation and informatization

PaddlePaddle basic usage details (four), PaddlePaddle training text classification model

IP message analysis notes

What smart contract? Principle analysis of DAPP contract system customization technology
随机推荐
[programming question] clear random number
[编程题]构造回文
Mysql-if-then-else statement
Ultimate doll 2.0 | observable practice sharing of cloud native PAAS platform
Analysis of advanced interview questions, Alibaba released the "limited edition" Android zero foundation dictionary
Leetcode1470. Rearrange array
Window7激活 电话激活小记;
Longest common substring
DEJA_VU3D - Cesium功能集 之 012-军事标绘系列六:自定义多边形
DEJA_ Vu3d - cesium feature set 012 - military plotting Series 6: Custom polygons
Reasons for MySQL backup failure of Tencent cloud database
[programming question] water bottle
Leetcode 386. Number of dictionary rows
14. System information viewing
MySQL modifies a field to auto increment
Detailed implementation of single layer neural network
SSLHandshakeException
喜讯,京准GPS北斗对时系统助力南亚电子管理系统
JVM - GC garbage collector
C thread call