面試題分享---多線程的順序執行與循環執行

最近在網上看到一篇關於多線程的面試題,平時雖然有看過一些併發的理論,但是實際編碼較少,因此也是特意練習一下。

題目描述:

怎麼讓線程A、線程B、線程C順序執行?

方案一:利用線程的join()方法,join()方法是線程類的實例方法,其作用是在當前線程中調用目標線程的join()方法,則當前線程進入Waiting狀態,目標線程執行完畢後當前線程纔再次進入Runable狀態。

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new ThreadA());
        Thread t2 = new Thread(new ThreadB(t1));
        Thread t3 = new Thread(new ThreadC(t2));

        t1.start();
        t2.start();
        t3.start();
    }

    static class ThreadA implements Runnable {
        @Override
        public void run() {
            System.out.println("ThreadA");
        }
    }

    static class ThreadB implements Runnable{

        private Thread thread;

        public ThreadB(Thread thread) {
            this.thread = thread;
        }
        @Override
        public void run() {
            try {
                //目標線程先執行完才繼續執行此線程執行體
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadB");
        }
    }

    static class ThreadC implements Runnable {

        private Thread thread;

        public ThreadC(Thread thread) {
            this.thread = thread;
        }
        @Override
        public void run() {
            try {
                //目標線程先執行完才繼續執行此線程執行體
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("ThreadC");
        }
    }

}

方案二:藉助線程池技術,newSingleThreadExecutor保證了其內只有一個線程在執行,且提交的線程執行體是按照FIFO的順序執行的。

public class ExecutorServiceDemo {

    public static void main(String[] args) {
        ExecutorService executorPool = Executors.newSingleThreadExecutor();
        executorPool.submit(new ThreadA());
        executorPool.submit(new ThreadB());
        executorPool.submit(new ThreadC());
    }

    static class ThreadA implements Runnable {
        @Override
        public void run() {
            System.out.println("ThreadA");
        }
    }

    static class ThreadB implements Runnable{
        @Override
        public void run() {
            System.out.println("ThreadB");
        }
    }

    static class ThreadC implements Runnable {
        @Override
        public void run() {
            System.out.println("ThreadC");
        }
    }

}

怎麼保證多個線程按順序循環執行一段代碼?

借鑑網上一種優雅的解決方案,但是原文的代碼我認爲有點問題,因爲它對線程內部的代碼加鎖對於其他線程來說是無效的。
原文鏈接:https://blog.csdn.net/feng15230805625/article/details/83350724

但是其思路是可以借鑑的,它利用鎖機制來實現對一個共享變量的互斥訪問,然後當這個共享變量等於特定值時執行特定的線程。下面是我的代碼:
對於add()方法,同一時間只能有一個線程執行它,然後在其內部持有一個計數器count,每次執行add()方法後修改計數器保證下一個線程執行add()方法。

public class CycleDemo {

    private static Integer count = 0;

    private synchronized static void add() {
        System.out.println(Thread.currentThread().getName());
        count++;

    }

    private static Integer get() {
        return count;
    }

    static class ThreadA implements Runnable {

        @Override
        public void run() {
            Thread.currentThread().setName("ThreadA");
            while (true) {
                if(get() % 3 == 0 && get() < 999) {
                    add(); //它保證了線程B在其後執行
                }
            }
        }
    }

    static class ThreadB implements Runnable {
        @Override
        public void run() {
            Thread.currentThread().setName("ThreadB");
            while (true) {
                if(get() % 3 == 1 && get() < 999) {
                    add();
                }
            }
        }
    }

    static class ThreadC implements Runnable {
        @Override
        public void run() {
            Thread.currentThread().setName("ThreadC");
            while (true) {
                if(get() % 3 == 2 && get() < 999) {
                    add();
                }
            }
        }
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new ThreadA());
        Thread t2 = new Thread(new ThreadB());
        Thread t3 = new Thread(new ThreadC());
        t3.start();
        t2.start();
        t1.start();
        
    }
}

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