線程同步面試題,3個線程打印一個1-100的數組,要求P1=1,P2=2,P3=3,P1=4的形式

當時沒有答好回來總結一下總結了兩個方式
一,這個方式是利用Object.notify(),Object.wait(),兩個方法來實現。
中心思想:保證應該到哪個線程打印時,只有該線程是喚醒狀態,其他都是暫停狀態。比如需要P1打印1,那就要讓P2,P3都是wait()狀態。

package com.example.ly.mydemo;


public class WaitObjectTest implements Runnable {
    private static int i = 0;
    private Object selfO = null;
    private Object pref = null;

    public WaitObjectTest(Object selfO, Object pref) {
        this.selfO = selfO;
        this.pref = pref;
    }

    @Override
    public void run() {
        System.out.println("threadId: " + Thread.currentThread().getName());
        while (i < 30) {
            synchronized (pref) {
                synchronized (selfO) {
                    System.out.println("threadId: " + Thread.currentThread().getName() + "  i: " + i);
                    i++;
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                        selfO.notify();
                }
                try {
                    pref.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {

        int[] object1 = new int[0];
        int[] object2 = new int[0];
        int[] object3 = new int[0];
        WaitObjectTest mRunnableA = new WaitObjectTest(object1, object3);
        WaitObjectTest mRunnableB = new WaitObjectTest(object2, object1);
        WaitObjectTest mRunnableC = new WaitObjectTest(object3, object2);

        Thread threadA = new Thread(mRunnableA, "A");
        Thread threadB = new Thread(mRunnableB, "B");
        Thread threadC = new Thread(mRunnableC, "C");
        threadA.start();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadB.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadC.start();
    }

}

二,這個方式我和朋友一個完善的一個方法,中心思想是:只synchronized數組,用循環來控制打印,就是打印需要的不需要的就continue。

   class A implements Runnable {

        Thread p1, p2, p3;
        int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8,9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
        int count = 0;

        public A() {
            p1 = new Thread(this,"0");
            p2 = new Thread(this,"1");
            p3 = new Thread(this,"2");
            p1.start();
            p2.start();
            p3.start();
        }

        @Override
        public void run() {

            while (count < arr.length) {
                synchronized (arr) {
                    String threadName = Thread.currentThread().getName();
                    if (count % 3 == Integer.valueOf(threadName)) {
                        LogUtils.writeLog("p:" + (Integer.valueOf(threadName)+1) + "=" + arr[count]);
                        count++;
                    } else {
                        continue;
                    }


                }
            }
        }
    }

總結:
1.第一個方法是朋友提供的,其實我不是很喜歡代碼多,可讀性差,但是第一個種方法可以幫助理解線程同步的原理,所以也貼出來大家一起學習一下。
2.第二種方法是我跟朋友一起總結出來的。是我自己覺得比較好的方式,畢竟核心代碼比較少,而且滿足了需求。
3.線程同步主要是synchronized關鍵字來控制訪問,必要時配合Object的Object.notify(),Object.wait(),兩個方法,實際上Java還提供了專門針對線程同步問題的類,回頭再針對線程同步問題做一篇總結吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章