CompletionService of Java concurrent programming

        I recently encountered a requirement, and one of the operations was time-consuming. In order to improve efficiency, I choose to open a new thread to do it asynchronously. Because of the need to operate on the return value of the method, I choose to use FutureTask, which can loop to get the task, and call the get method to get the task execution result, but if the task has not been completed, the thread that gets the result will block until the task is completed. Later found the CompletionService class, which integrates the functions of Executor and BlockingQueue. You can submit the Callable task to it for execution, and then use the take method similar to the queue to get the thread's return value.

The demo is as follows:

package com.aliyun.callback;

import org.junit.Test;

import java.util.Random;
import java.util.concurrent.*;

/**
 * Created by Demon, on 2018/4/25
 */
public class CompletionServiceTest {

    private static final int DEFAULT_CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() <= 1 ? 2 :
            Runtime.getRuntime().availableProcessors() * 2;

    private static final int DEFAULT_MAXNUM_POOL_SIZE = 32;

    private static final int DEFAULT_KEEP_ALIVE_TIME = 30;

    private  ThreadPoolExecutor threadPool = new ThreadPoolExecutor(DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXNUM_POOL_SIZE
            , DEFAULT_KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20));

    @Test
    public void test() {
        CompletionService<String> completionService = new ExecutorCompletionService<>(threadPool);
        try {
            for (int i = 0; i < 5; i++) {
                Task task = new Task("threadName" + i);
                // 使用submit 主线程可以捕捉到异步线程中的异常
                completionService.submit(task);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 5; i++) {
            try {
                Future<String> future = completionService.take();
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

    private class Task implements Callable<String> {

        private String name;

        private Task(String name) {
            this.name = name;
        }

        @Override
        public String call() throws Exception {
            int sleepTime = new Random().nextInt(1000);
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 返回给调用者的值
            String str = name + " sleep time:" + sleepTime;
            System.out.println(name + " finished...");
            // throw new RuntimeException("test catch error");
            return str;
        }
    }
}
运行结果:
threadName0 finished...
threadName0 sleep time:140
threadName4 finished...
threadName4 sleep time:250
threadName3 finished...
threadName3 sleep time:258
threadName1 finished...
threadName1 sleep time:416
threadName2 finished...
threadName2 sleep time:712

When using CompletionService to maintain the return result of the processing thread, the main thread can always get the return value of the task completed first , regardless of the order in which they are added to the thread pool, which can reduce the blocking time of the main thread, which is better than the native future .get method.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325247800&siteId=291194637