ExecutorCompletionService的使用

一、背景

項目中我們經常會處理這樣一種業務場景。啓動多個線程去計算一段業務邏輯,等待所有線程全部執行完畢之後再向下做業務邏輯處理。在java中爲我們提供了ExecutorCompletionService可以輕鬆的實現這樣的業務場景。當然,還有其他中辦法可以實現,比如使用CountDownLatch也可以達到同樣的目的。


二、代碼實戰

先說一下代碼具體實現的思路。
定義一個類MyExecutorCompletionService繼承ExecutorCompletionService。並定義submittedTasks表示已經提交的任務,completedTasks表示已經完成的任務數,因爲是多線程執行,所以這兩個變量定義爲AtomicLong類型,以確保線程安全訪問。利用Executors創建一個大小爲5的固定線程池,模擬啓動20個任務執行。每次提交任務都調用MyExecutorCompletionService的submitTask,在submitTask會調用ExecutorCompletionService的submit方法執行任務,並將submittedTasks加1。循環判斷任務是否完成,若未完成則調用getEleByTake一直阻塞等待線程完成,並將completedTasks加1。當完成線程數等於完成線程數,則表示所有線程都已經執行完畢。


請看代碼:

package concurrent;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;


public class ExecutorCompletionServiceTest {


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorCompletionServiceTest executorCompletionServiceTest = new ExecutorCompletionServiceTest();
        executorCompletionServiceTest.test();
    }

    private void test() throws ExecutionException, InterruptedException {
        int numThread = 5;
        int taskNum = 20;
        ExecutorService executor = Executors.newFixedThreadPool(numThread);
        MyExecutorCompletionService myExecutorCompletionService = new MyExecutorCompletionService<String>(executor);
        for(int i = 0;i<taskNum;i++ ){
            myExecutorCompletionService.submitTask(new ExecutorCompletionServiceTest.Task(i));
        }
        while(myExecutorCompletionService.isTasksCompleted()) {
            System.out.println("blocking================");
     /*       if(myExecutorCompletionService.getEleByPoll()==null) {
                continue;
            }*/
            myExecutorCompletionService.getEleByTake();
            if(myExecutorCompletionService.completedTasks.get()==myExecutorCompletionService.submittedTasks.get()) {
                break;
            }
        }
        executor.shutdown();
        System.out.println("end===============");
    }
    static class Task implements Callable<String>{
        private int i;

        public Task(int i){
            this.i = i;
        }

        public String call() throws Exception {
            System.out.println(Thread.currentThread().getName() + "執行完任務:" + i);
            return Thread.currentThread().getName() + "執行完任務:" + i;
        }
    }

    class MyExecutorCompletionService<V> extends ExecutorCompletionService<V> {

        //提交的任務數量
        private final AtomicLong submittedTasks = new AtomicLong();
        //已經執行完成的任務數量
        private final AtomicLong completedTasks = new AtomicLong();

        public MyExecutorCompletionService(Executor executor) {
            super(executor);
        }

        public MyExecutorCompletionService(Executor executor, BlockingQueue<Future<V>> queue) {
            super(executor, queue);
        }

        public Future<V> submitTask(Callable<V> task) {
            Future<V> future = super.submit(task);
            submittedTasks.incrementAndGet();
            System.out.println("submit()====================");
            return future;
        }

        public Future<V> submitTask(Runnable task, V result) {
            Future<V> future = super.submit(task, result);
            submittedTasks.incrementAndGet();
            return future;
        }

        /**
         * 阻塞方法,等待返回下一個執行完成任務的Future
         */
        public Future<V> getEleByTake() throws InterruptedException {
            System.out.println("take()====================");
            Future<V> future = super.take();
            completedTasks.incrementAndGet();
            return future;
        }

        /**
         * 非阻塞方法,如果有執行完成的任務,返回Future,如果無執行完成的任務,返回null;
         */
        public Future<V> getEleByPoll() {
            Future<V> future = super.poll();
            System.out.println("poll()================");
            if (future != null)
                completedTasks.incrementAndGet();
            return future;
        }

        public Future<V> getEleByPoll(long timeout, TimeUnit unit) throws InterruptedException {
            Future<V> future = super.poll(timeout, unit);
            if (future != null)
                completedTasks.incrementAndGet();
            return future;
        }

        public long getNumberOfCompletedTasks() {
            return completedTasks.get();
        }

        public long getNumberOfSubmittedTasks() {
            return submittedTasks.get();
        }

        public boolean isTasksCompleted() {
            return completedTasks.get() < submittedTasks.get();
        }
    }
}


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