异步任务的封装与结果获取--CompletableFuture&CompletionService的使用

1、CompletableFuture 可以很方便的实现异步任务的封装 并实现结果的联合等一系列操作,轻松实现 任务的并行

package com.csdn.test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * CompletableFuture 可以很方便的实现异步任务的封装 并实现结果的联合等一系列操作
 */
public class TestCompletableFuture
{
    // CompletableFuture基本用法
    private static Future<String> asyncTask(String input)
    {
        // CompletableFuture包装返回结果
        CompletableFuture<String> future = new CompletableFuture<String>();
        new Thread(()->{
            try
            {
                TimeUnit.SECONDS.sleep(1);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
            System.out.println("async task input value: " + input);
            try
            {
                String ret = input.substring(1);
                future.complete(ret);
            }
            catch(Exception ex)
            {
                // 封装异常
                future.completeExceptionally(ex);
            }
        }).start();
        return future;
    }
    
    // 使用工厂创建CompletableFuture
    private static Future<String> asyncTask(int input)
    {
        return CompletableFuture.supplyAsync(() -> {
            return String.valueOf(20/input);
        });
    }
    
    // 异步处理流水线
    private static List<String> asyncTaskPipeline(List<String> strList)
    {
        final Executor executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), 
            new ThreadFactory()
            {
                public Thread newThread(Runnable r)
                {
                    Thread t = new Thread(r);
                    t.setDaemon(true); // 设置为守护线程,这种方式不会阻止程序的关停
                    return t;
                }
            });
        List<CompletableFuture<String>> retFuture = strList.stream().map(str -> CompletableFuture.supplyAsync(()->str.trim(), executor))
                                                                .map(future -> future.thenApply(String::trim))
                                                                .map(future -> future.thenCompose(str -> CompletableFuture.supplyAsync(()->str.trim(), executor)))
                                                                .collect(Collectors.toList());
        return retFuture.stream()
                        .map(CompletableFuture::join) // 等待流中Future执行完毕,提取各自返回值
                        .collect(Collectors.toList());
    }
    
    public static void main(String[] args)
    {
        String input = " trim";
        System.out.println("async task start ...");
        Future<String> future = asyncTask(input);
        // 出现异常场景 验证
        Future<String> futureInt = asyncTask(0);
        // do something else
        System.out.println("do something else...");
        try
        {
            // 也可 CompletableFuture.allOf(futuresArr).join() 等待所有与future任务结束
            String str = future.get();
            System.out.println("async task result: " + str);
            System.out.println("async task result: " + futureInt.get());
        }
        catch(Exception ex)
        {
            System.out.println("Exception: " + ex.getMessage());
        }
        String[] arr = new String[]{"aa", "bb "};
        System.out.println(asyncTaskPipeline(Arrays.asList(arr)));
    }
}

输出:

async task start ...
do something else...
async task input value:  trim
async task result: trim
Exception: java.lang.ArithmeticException: / by zero
[aa, bb]
 

2、CompletionService 提供了异步任务的执行与结果的封装,轻松实现多线程任务,并方便的集中处理上述任务的结果(且任务最先完成的先返回)

package com.csdn.test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestCompletionService
{
    // 线程池超时关闭控制
    private static final int TIMEOUT = 300000;

    // 单位统一为毫秒
    private static final TimeUnit UNIT = TimeUnit.MILLISECONDS;
    
    // CompletableFuture基本用法
    private static void asyncTask(int poolSize, List<String> strList)
    {
        // 1、创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(poolSize);
        // 2、创建多线程任务执行器
        CompletionService<String> completionService = new ExecutorCompletionService<String>(executor);
        // 3、提交任务
        for (String str : strList)
        {
            completionService.submit(new Callable<String>()
            {

                @Override
                public String call() throws Exception
                {
                    return str.trim();
                }

            });
        }
        // 4、获取数据
        try
        {
            for (int taskCount = 0, size = strList.size(); taskCount < size; taskCount++)
            {
                System.out.println("future result: " + completionService.take().get());
            }
        }
        catch (InterruptedException | ExecutionException e)
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            // 5、关闭线程池
            try
            {
                executor.shutdownNow();
                executor.awaitTermination(TIMEOUT, UNIT);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args)
    {
        String[] arr = new String[]{"aa", "bb "};
        asyncTask(2, Arrays.asList(arr));
    }
}

输出:

future result: aa
future result: bb

参考书籍:

《Java8实战》

《Java并发编程实战》

参考博客:

https://blog.csdn.net/zhangphil/article/details/80670593

猜你喜欢

转载自blog.csdn.net/zangdaiyang1991/article/details/84333995