百度面試經歷之設計一個異步執行隊列

面試官提出一個問題:設計一個異步執行的隊列。我的第一想法是採用阻塞隊列,提供向阻塞隊列中添加任務的方法,提供啓動任務隊列中任務的方法,當時的思路比較模糊,在這裏寫一下。在代碼中雖然使用了阻塞隊列,但並沒有使用阻塞隊列的特性。基本上實現了面試官所要求的功能,代碼如下

public class AsyncRunnableQueue {
    private static class AsyncRunnableQueueHolder{
        private static final AsyncRunnableQueue INSTANCE = new AsyncRunnableQueue();
    }

    //維護一個阻塞隊列
    LinkedBlockingQueue<Runnable> linkedBlockingQueue;
    //串行執行線程
    Thread thread;
    //並行執行線程池
    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(12);
    //停止標誌
    boolean isStop;

    private AsyncRunnableQueue(){
        linkedBlockingQueue = new LinkedBlockingQueue<>();
    }
    //單例模式維護
    public static final AsyncRunnableQueue getInstance(){
        return AsyncRunnableQueueHolder.INSTANCE;
    }

    public void addRunnable(Runnable runnable){
        if(linkedBlockingQueue != null){
            linkedBlockingQueue.offer(runnable);
        }
    }

    /**
     * 串行執行所有Runnable
     */
    public void runAllTaskSerial() {
        isStop = false;
        if (thread == null) {
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (!isStop && linkedBlockingQueue.peek() != null) {
                        System.out.println("Serial thread name:"+Thread.currentThread().getName());
                        Runnable runnable = linkedBlockingQueue.poll();
                        runnable.run();
                    }
                }
            });
        }
        if (!isStop) {
            thread.start();
        }
    }

    /**
     * 並行執行runnable
     * 串行執行中所有的runnable均在一個線程中串行執行,若runnable是耗時任務,則需要開啓多個線程並行執行
     * 這裏我們使用線程池
     */
    public void runTaskParallel(){
        isStop = false;
        while(!isStop && linkedBlockingQueue.peek() != null){
            if(fixedThreadPool != null){
                fixedThreadPool.execute(linkedBlockingQueue.poll());
            }
        }
    }

    public void stop(){
        isStop = true;
    }
}

測試代碼:

public class AsyncRunnableQueueTest {
    public static void main(String[] args) {
        AsyncRunnableQueue queue = AsyncRunnableQueue.getInstance();
        queue.addRunnable(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable 1 currentThread:"+Thread.currentThread().getName());
            }
        });
        queue.addRunnable(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable 2 currentThread:"+Thread.currentThread().getName());
            }
        });
        queue.addRunnable(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable 3 currentThread:"+Thread.currentThread().getName());
            }
        });
//        queue.runAllTaskSerial();
        queue.runTaskParallel();
    }
}

結果:

並行執行結果:

runnable 1 currentThread:pool-1-thread-1
runnable 2 currentThread:pool-1-thread-2
runnable 3 currentThread:pool-1-thread-3

可以看到,三個runnable是在三個不同的線程中跑的

串行執行結果:

Serial thread name:Thread-0
runnable 1 currentThread:Thread-0
Serial thread name:Thread-0
runnable 2 currentThread:Thread-0
Serial thread name:Thread-0
runnable 3 currentThread:Thread-0

可以看到,三個runnable是在同一個線程中串行執行

有興趣的同學可以一起討論

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