很多人都想进 BAT,但是并不是每个人都能如愿。BAT 的面试非常的严格,今年春招,阿里的一道线程面试题,就淘汰了无数的人!
今天我对这道题,分别用了 3 种不同的方法实现了,供大家参考!
题目如下:
通过N个线程顺序循环打印从0至100,如给定N=3则输出:
thread0: 0
thread1: 1
thread2: 2
thread0: 3
thread1: 4
…..
第一种,通过判断执行状态来实现。
static int result = 0;
public static void orderPrintNum(final int n){
final boolean [] printFlag = new boolean [n];
for (int i = 0; i < n; i++) {
final int index = i;
if(0 == i){
printFlag[index] = true;
}
new Thread(new Runnable() {
public void run() {
try {
while (result <= 100) {
if(printFlag[index]){
System.out.println("thread" + index + ": " + result++);
printFlag[index] = false;
if(index == (n - 1)){
printFlag[0] = true;
}else {
printFlag[index + 1] = true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
想到这种方式的,应该就能想到信号量。因此,第二种实现方法就是通过信号量来实现。
static int result = 0;
public static void orderPrintNum2(final int n) throws InterruptedException{
// N 个线程
Thread [] threads = new Thread[n];
// N 个Semaphore
final Semaphore[] syncSemaphore = new Semaphore[n];
for (int i = 0; i < n; i++) {
//非公平信号量,计数为1
syncSemaphore[i] = new Semaphore(1);
if (i != n-1){
//获取一个许可前线程将一直阻塞
syncSemaphore[i].acquire();
}
}
for (int i = 0; i < n; i++) {
final Semaphore lastSemphore = i == 0 ? syncSemaphore[n - 1] : syncSemaphore[i - 1];
final Semaphore curSemphore = syncSemaphore[i];
final int index = i;
threads[i] = new Thread(new Runnable() {
public void run() {
try {
while (true) {
lastSemphore.acquire();
System.out.println("thread" + index + ": " + result++);
if (result > 100){
System.exit(0);
}
curSemphore.release();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
threads[i].start();
}
}
第三种,通过 wait 和 notifyAll 来实现。
static int result = 0;
public static void orderPrintNum3(final int n) {
final Object LOCK = new Object();
final int [] flag = new int[1];
for (int i = 0;i < n; i++){
final int index = i;
new Thread(new Runnable() {
public void run() {
try {
while (result <= 100) {
synchronized (LOCK){
if(flag[0] == index){
System.out.println("thread" + index + ": " + result++);
flag[0] = index == n - 1 ? 0 : index + 1;
// 唤醒其他wait线程
LOCK.notifyAll();
}else {
LOCK.wait();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
3 种方法的运行效果,截图如下:

除此之外,还可以通过队列,链表等形式来实现。具体,大家去思考思考吧!
: » 阿里的一道线程面试题,面哭了无数人
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/252054.html