很多人都想进 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/java/252054.html