How to wait for all threads to finish, using ExecutorService?

前端 未结 26 2584
你的背包
你的背包 2020-11-22 01:55

I need to execute some amount of tasks 4 at a time, something like this:

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
    tas         


        
26条回答
  •  情书的邮戳
    2020-11-22 02:54

    I created the following working example. The idea is to have a way to process a pool of tasks (I am using a queue as example) with many Threads (determined programmatically by the numberOfTasks/threshold), and wait until all Threads are completed to continue with some other processing.

    import java.util.PriorityQueue;
    import java.util.Queue;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /** Testing CountDownLatch and ExecutorService to manage scenario where
     * multiple Threads work together to complete tasks from a single
     * resource provider, so the processing can be faster. */
    public class ThreadCountDown {
    
    private CountDownLatch threadsCountdown = null;
    private static Queue tasks = new PriorityQueue<>();
    
    public static void main(String[] args) {
        // Create a queue with "Tasks"
        int numberOfTasks = 2000;
        while(numberOfTasks-- > 0) {
            tasks.add(numberOfTasks);
        }
    
        // Initiate Processing of Tasks
        ThreadCountDown main = new ThreadCountDown();
        main.process(tasks);
    }
    
    /* Receiving the Tasks to process, and creating multiple Threads
    * to process in parallel. */
    private void process(Queue tasks) {
        int numberOfThreads = getNumberOfThreadsRequired(tasks.size());
        threadsCountdown = new CountDownLatch(numberOfThreads);
        ExecutorService threadExecutor = Executors.newFixedThreadPool(numberOfThreads);
    
        //Initialize each Thread
        while(numberOfThreads-- > 0) {
            System.out.println("Initializing Thread: "+numberOfThreads);
            threadExecutor.execute(new MyThread("Thread "+numberOfThreads));
        }
    
        try {
            //Shutdown the Executor, so it cannot receive more Threads.
            threadExecutor.shutdown();
            threadsCountdown.await();
            System.out.println("ALL THREADS COMPLETED!");
            //continue With Some Other Process Here
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
    
    /* Determine the number of Threads to create */
    private int getNumberOfThreadsRequired(int size) {
        int threshold = 100;
        int threads = size / threshold;
        if( size > (threads*threshold) ){
            threads++;
        }
        return threads;
    }
    
    /* Task Provider. All Threads will get their task from here */
    private synchronized static Integer getTask(){
        return tasks.poll();
    }
    
    /* The Threads will get Tasks and process them, while still available.
    * When no more tasks available, the thread will complete and reduce the threadsCountdown */
    private class MyThread implements Runnable {
    
        private String threadName;
    
        protected MyThread(String threadName) {
            super();
            this.threadName = threadName;
        }
    
        @Override
        public void run() {
            Integer task;
            try{
                //Check in the Task pool if anything pending to process
                while( (task = getTask()) != null ){
                    processTask(task);
                }
            }catch (Exception ex){
                ex.printStackTrace();
            }finally {
                /*Reduce count when no more tasks to process. Eventually all
                Threads will end-up here, reducing the count to 0, allowing
                the flow to continue after threadsCountdown.await(); */
                threadsCountdown.countDown();
            }
        }
    
        private void processTask(Integer task){
            try{
                System.out.println(this.threadName+" is Working on Task: "+ task);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
    }
    

    Hope it helps!

提交回复
热议问题