1. 程式人生 > >面試題:常見的多執行緒實戰手撕程式碼(順序列印數字、字母)

面試題:常見的多執行緒實戰手撕程式碼(順序列印數字、字母)

問題一:

  一個多執行緒的問題,用三個執行緒,順序列印字母A-Z,輸出結果是1A 2B 3C 1D 2E…列印完畢最後輸出一個Ok。

程式碼一:

public class forCharacter {
    private static char c = 'A';
    private static int i = 0;
    public static void main(String[] args) throws InterruptedException {
        Runnable r = new Runnable() {
            public
void run() { int threadId = Integer.parseInt(Thread.currentThread().getName()); while(i < 26){ if(i % 3 == threadId - 1){ System.out.println("執行緒id:" + threadId + " " + (char)c++); i++; if
(i == 26) System.out.println("哈哈,祝拿到offer!"); } try{ Thread.sleep(1000); }catch(InterruptedException e){ e.printStackTrace(); } } } }; Thread t1 = new
Thread(r, "1"); Thread t2 = new Thread(r, "2"); Thread t3 = new Thread(r, "3"); t1.start(); t2.start(); t3.start(); } }

  但是程式碼一存在問題:這樣寫的話,可能會造成資源浪費,所以我們可以通過加鎖進行限制,但是加鎖後,因為sleep不會釋放鎖,會導致其他執行緒無法獲得執行機會。因此需要配合wait和notifyAll。

程式碼二:

public class forCharacter {
    /*
     * Description:一個多執行緒的問題,用三個執行緒,順序列印字母A-Z,輸出結果是1A 2B 3C 1D 2E...列印完畢最後輸出一個Ok
     * Author:ZhangRuirui 
     * Date:2018/05/25 
     * Email:[email protected]
     */
    private static char c = 'A';// 必要的時候宣告為volatile型別的
    private static int i = 0;

    public static void main(String[] args) throws InterruptedException {
        Runnable r = new Runnable() {
            public void run() {
                synchronized (this) {
                    try {
                        int threadId = Integer.parseInt(Thread.currentThread().getName());
                        System.out.println("當前執行緒id:" + threadId + " ");
                        while (i < 26) {
                            if (i % 3 == threadId - 1) {
                                System.out.println("執行緒id:" + threadId + " " + (char) c++);
                                i++;
                                if (i == 26)
                                    System.out.println("哈哈,祝拿到offer!");
                                notifyAll();// 喚醒其他執行緒
                            } else {
                                wait();// 阻塞其他執行緒
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread t1 = new Thread(r, "1");
        Thread t2 = new Thread(r, "2");
        Thread t3 = new Thread(r, "3");
        t1.start();
        t2.start();
        t3.start();
    }
}

輸出:

當前執行緒id1 
執行緒id1 A
當前執行緒id2 
執行緒id2 B
當前執行緒id3 
執行緒id3 C
執行緒id1 D
執行緒id2 E
執行緒id3 F
執行緒id1 G
執行緒id2 H
執行緒id3 I
執行緒id1 J
執行緒id2 K
執行緒id3 L
執行緒id1 M
執行緒id2 N
執行緒id3 O
執行緒id1 P
執行緒id2 Q
執行緒id3 R
執行緒id1 S
執行緒id2 T
執行緒id3 U
執行緒id1 V
執行緒id2 W
執行緒id3 X
執行緒id1 Y
執行緒id2 Z
哈哈,祝拿到offer!

問題二:(快手)

  一個多執行緒的問題,用五個執行緒,順序列印數字1~無窮大,其中每5個數字為1組,如下:其中id代表執行緒的id

id   1   2   3   4   5
no   1   2   3   4   5
no   6   7   8   9   10
no   11  12  13  14  15
no   ..  ..  ..  ..  ..

程式碼:

public class forCharacter2 {

    /*
     * Description:一個多執行緒的問題,用五個執行緒,順序列印數字1~無窮大,其中每5個數字為1組 
     * Author:ZhangRuirui
     * Date:2018/05/25 
     * Email:[email protected]
     */
    private static volatile int orderNum = 1;// 必要的時候宣告為volatile型別的

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                synchronized (this) {
                    try {
                        int threadId = Integer.parseInt(Thread.currentThread().getName());
                        while (true) {
                            if (orderNum % 5 == threadId || orderNum % 5 == 0) {
                                if (orderNum % 5 == 0)
                                    System.out.println("threadid = " + 5 + " " + orderNum++);
                                else
                                    System.out.println("threadid = " + threadId + " " + orderNum++);
                                Thread.sleep(1000);// 為了執行效果看的更清楚
                                notifyAll();
                            } else {
                                wait();
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        Thread t1 = new Thread(r, "1");
        Thread t2 = new Thread(r, "2");
        Thread t3 = new Thread(r, "3");
        Thread t4 = new Thread(r, "4");
        Thread t5 = new Thread(r, "5");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

輸出:

threadid = 1 1
threadid = 2 2
threadid = 3 3
threadid = 4 4
threadid = 5 5
threadid = 1 6
threadid = 2 7
threadid = 3 8
threadid = 4 9
threadid = 5 10
threadid = 1 11
threadid = 2 12
threadid = 3 13
threadid = 4 14
threadid = 5 15
threadid = 1 16
threadid = 2 17
下面死迴圈不斷輸出

—–樂於分享,共同進步,歡迎補充
—–Any comments greatly appreciated
—–誠心歡迎各位交流討論!QQ:1138517609