1. 程式人生 > 實用技巧 >試試,阿里P7的筆試題:多執行緒按序列印如何實現?

試試,阿里P7的筆試題:多執行緒按序列印如何實現?

下面是阿里 P7 的一道筆試題,公眾號【Java鬥帝】內回覆666有免費電子書贈送

1、題目

編寫一個程式,開啟 3 個執行緒,這 3 個執行緒的 ID 分別為 A、B、C,3 個執行緒交替列印 1-100 的整數,樣例 Sample:

Thread1:1
Thread2:2
Thread3:3
Thread1:4
Thread2:5
Thread3:6
....
Thread3:99
Thread1:100

大家可以先思考一下,試試看看能否實現?

2、解題思路

題目中要求 3 個執行緒啟動之後,需要按順序一個接著一個來執行,重點是 3 個執行緒都處於執行狀態,如何能讓他們按順序來列印?

大家可以把 3 個執行緒想象為 3 個人(ABC),ABC 3 個人手拉手組成一個環,然後 3 個人都坐那等通知,等誰的通知呢,等待上一個人的通知,B 等待 A 的通知,C 等待 B 的通知,A 等待 C 的通知。

剛開始:程式先喚起 A,A 列印之後,通知 B,然後 A 進入休眠等待喚醒通知,此時輪到 B 列印了,B 列印之後通知 C,B 進入休眠等待喚醒通知,此時輪到 C 列印了,C 列印之後通知 A,C 進入休眠等待喚醒通知,通過這種方式來實現,每個執行緒列印之後,負責喚醒下一個執行緒,然後自己進入休眠狀態。

關鍵技術點有 2 個:

1、阻塞執行緒

2、喚起執行緒

java.util.concurrent.locks.LockSupport類剛好提供了 2 個靜態方法支援這些操作

1、park():讓當前執行緒阻塞

2、unpark(Thread thread):用來喚起阻塞中的執行緒

3、答案

程式碼相當簡單。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.LockSupport;

public class ThreadTest {
    static List<Thread> threadList = new ArrayList<>();//存放執行緒的集合
    static int threadSize = 3;//總共多少個執行緒
    static int threadIndex = 0;//當前執行緒下標
    static int maxValue = 100;//需要輸出的數的最大值
    static int curValue = 1;//數的當前值

    public static void main(String[] args) throws InterruptedException {
        //建立執行緒
        for (int i = 1; i <= threadSize; i++) {
            Thread thread = new Thread(() -> {
                while (true) {
                    //阻塞當前執行緒
                    LockSupport.park();
                    //當前的值需要小於最大值
                    if (curValue <= maxValue) {
                        System.out.println(Thread.currentThread().getName() + ":" + curValue++);
                    } else {
                        break;
                    }
                    //喚起下一個執行緒
                    LockSupport.unpark(threadList.get(++threadIndex % threadList.size()));
                }
                //喚起所有執行緒
                threadList.forEach(LockSupport::unpark);
            });
            thread.setName(String.format("Thread%d", i));
            threadList.add(thread);
        }

        //啟動所有執行緒
        for (Thread thread : threadList) {
            thread.start();
        }

        //喚起第一個執行緒
        LockSupport.unpark(threadList.get(0));
    }
}

推薦閱讀

為什麼阿里巴巴的程式設計師成長速度這麼快,看完他們的內部資料我懂了

程式設計師達到50W年薪所需要具備的知識體系。

—小時解讀併發程式設計三大特性

關於【暴力遞迴演算法】你所不知道的思路

看完三件事❤️

如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:

點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。

關注公眾號 『 Java鬥帝 』,不定期分享原創知識。

同時可以期待後續文章ing