将一个简单远程调用的方式例子改为异步调用

将一个简单远程调用的方式例子改为异步调用

package com.xsxy.asynctest.test03;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 将一个简单远程调用的方式例子改为异步调用
 */
public class Test04CompletableFuturePractice {

    public static void main(String[] args) {
        List<String> ipList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            ipList.add("192.168.0." + i);
        }
        syncMethod(ipList);
        AsyncMethod(ipList);
    }

    /**
     * 同步顺序调用耗时 time:10138
     *
     * @param ipList
     */
    public static void syncMethod(List<String> ipList) {
        long start = System.currentTimeMillis();
        ipList.forEach(ip -> {
            rpcCall(ip, 8080);
        });
        System.out.println("time:" + (System.currentTimeMillis() - start));
    }

    /**
     * 异步调用耗时 time:4029
     *
     * @param ipList
     */
    public static void AsyncMethod(List<String> ipList) {
        long start = System.currentTimeMillis();
        // 同步调用转异步
        List<CompletableFuture<String>> completableFutureList = ipList.stream().map(ip -> CompletableFuture.supplyAsync(() -> rpcCall(ip, 9090)))
                .collect(Collectors.toList());

        // 阻塞等待所有调用都结束
        List<String> resList = completableFutureList.stream().map(CompletableFuture::join).collect(Collectors.toList());
        // resList.forEach(System.out::println);

        System.out.println("time:" + (System.currentTimeMillis() - start));
    }


    public static String rpcCall(String ip, int port) {
        System.out.println("rpcCall=ip:" + ip + ",port:" + port);
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {

        }
        return "res" + port;
    }
}

其他completableFuture的使用例子

package com.xsxy.asynctest.test03;

import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class Test01CompletableFutureSet {
    public static final int AVALIABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(AVALIABLE_PROCESSORS, AVALIABLE_PROCESSORS, 1, TimeUnit.MINUTES,
            new LinkedBlockingQueue<>(5), new ThreadPoolExecutor.CallerRunsPolicy());


    public static void main(String[] args) throws Exception {
        // waitNotify();
        // runAsync();
        // runAsync1WithBizExecutor();
        // supplyAsync();
        // thenRun();
        thenAccept();
    }

    /**
     * 这里使用CompletableFuture实现了 通知等待模型,主线程调用future的get()方法等待future返回结果,一开始由于future结果没有设置,
     * 所以主线程被阻塞挂起,等异步任务休眠3s,然后调用future的complete方法模拟主线程等待的条件完成,这时候主线程就会从get()方法返回。
     */
    public static void waitNotify() throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture completableFuture = new CompletableFuture();
        executor.execute(() -> {
            System.out.println("executor sleep 3 seconds");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {

            }

            completableFuture.complete("executor done");
        });

        System.out.println("main wait completableFurture result");
        // 阻塞获取completableFuture结果
        System.out.println(completableFuture.get());
        // 设置超时时间,超时时会保timeoutException异常
        // System.out.println(completableFuture.get(1, TimeUnit.SECONDS));
        System.out.println("main end");
    }

    /**
     * 实现无返回值的异步计算:当你想异步执行一个任务,并且不需要任务的执行结果时可以使用该方法,比如异步打日志,异步做消息通知等
     * 在默认情况下,runAsync(Runnablerunnable)方法是使用整个JVM内唯一的ForkJoinPool.commonPool()线程池来执行异步任务的,
     * 使用runAsync (Runnable runnable, Executor executor)
     */
    public static void runAsync() throws Exception {
        CompletableFuture future = CompletableFuture.runAsync(() -> {
            System.out.println("execute completableFuture task");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {

            }
        });

        System.out.println("mian");
        // 无返回值
        System.out.println(future.get());
        System.out.println("main end");
    }

    /**
     * 使用自定义线程池 实现无返回值的异步计算
     */
    public static void runAsync1WithBizExecutor() throws Exception {
        // 使用自定义的线程池
        CompletableFuture future = CompletableFuture.runAsync(() -> {
            System.out.println("run completableFuture task");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {

            }
        }, executor);

        System.out.println("main");
        System.out.println(future.get());
        System.out.println("main end");
    }

    /**
     * 实现有返回值的异步计算
     * 在默认情况下,supplyAsync(Supplier<U> supplier)方法是使用整个JVM内唯一的ForkJoinPool.commonPool()线程池来执行异步任务的,
     * 使用supply-Async(Supplier<U> supplier,Executor executor)方法允许我们使用自己制定的线程池来执行异步任务
     */
    public static void supplyAsync() throws Exception {
        CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<Object>() {
            @Override
            public Object get() {
                System.out.println("completableFuture supplyAsync run");
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (Exception e) {

                }
                // 返回异步计算结果
                return "supplyAsync return";
            }
        });

        System.out.println("main");
        System.out.println(future.get());
        System.out.println("main end");
    }

    /**
     * 基于thenRun实现异步任务,执行完毕后,激活异步任务B执行,需要注意的是,这种方式激活的异步任务B是拿不到任务A的执行结果的
     */
    public static void thenRun() throws ExecutionException, InterruptedException {
        CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                System.out.println("completableFuture run");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (Exception e) {

                }
                return "completableFuture supplyAsync return";
            }
        });

        CompletableFuture futuretwo = future.thenRun(() -> {
            System.out.println("thenRun  --");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {

            }
        });

        System.out.println("main");
        System.out.println(futuretwo.get());
        System.out.println("main end");
    }

    /**
     * 基于thenAccept实现异步任务,执行完毕后,激活异步任务B执行,需要注意的是,这种方式激活的异步任务B是可以拿到任务A的执行结果的
     */
    public static void thenAccept() throws ExecutionException, InterruptedException {
        CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                System.out.println("completableFuture run");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (Exception e) {

                }
                return "completableFuture supplyAsync return";
            }
        });

        CompletableFuture futuretwo = future.thenAccept(new Consumer<String>() {
            @Override
            public void accept(String o) {
                System.out.println(o);
            }
        });

        System.out.println("main");
        System.out.println(futuretwo.get());
        System.out.println("main end");
    }
}

package com.xsxy.asynctest.test03;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;


public class Test02TwoCompletableFuture {


    /**
     * CompletableFuture功能强大的原因之一是其可以让两个或者多个Completable-Future进行运算来产生结果
     * <p>
     * main函数中首先调用方法doSomethingOne("123")开启了一个异步任务,并返回了对应的CompletableFuture对象,
     * 我们取名为future1,然后在future1的基础上调用了thenCompose方法,企图让future1执行完毕后,激活使用其结果作
     * 为doSomethingTwo(String companyId)方法的参数的任务
     */
    public static void main(String[] args) throws Exception {
        // 串行
        // testThenCompose();
        // 并行计算
        // testThencombine();
        // 批量
        testAllOf();

    }

    /**
     * 基于thenCompose实现当一个CompletableFuture执行完毕后,执行另外一个CompletableFuture
     */
    public static void testThenCompose() throws Exception {
        CompletableFuture<String> future = doSomething1("123").thenCompose(id -> doSomething2(id));
        // CompletableFuture<String> future = doSomething1("123").thenCompose(Test02TwoCompletableFuture::doSomething2);
        System.out.println("main");
        System.out.println(future.get());
        System.out.println("main end");
    }

    /**
     * 基于thenCombine实现当一个CompletableFuture执行完毕后,执行另外一个CompletableFuture
     */
    public static void testThencombine() throws Exception {
        // CompletableFuture<String> future = doSomething1("123").thenCombine(doSomething2("456"), (str1, str2) -> str1 + ":" + str2);
        CompletableFuture<String> future = doSomething1("123").thenCombine(doSomething2("456"), (str1, str2) -> {
            return str1 + ":" + str2;
        });
        System.out.println("main");
        System.out.println(future.get());
        System.out.println("main end");
    }

    /**
     * 基于allOf等待多个并发运行的CompletableFuture任务执行完毕
     *
     * 调用了四次doSomethingOne方法,分别返回一个CompletableFuture对象,然后收集这些CompletableFuture到futureList列表。
     * 调用allOf方法把多个CompletableFuture转换为一个result,代码3在result上调用get()方法会阻塞调用线程,
     * 直到futureList列表中所有任务执行完毕才返回
     */
    public static void testAllOf() throws ExecutionException, InterruptedException {
        List<CompletableFuture<String>> futureList = new ArrayList<>();
        futureList.add(doSomething1("1"));
        futureList.add(doSomething1("2"));
        futureList.add(doSomething1("3"));
        futureList.add(doSomething1("4"));

        CompletableFuture<Void> res = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
        System.out.println("main");
        // 等待所有的future执行完毕
        System.out.println(res.get());
        System.out.println("main end ");

    }


    public static CompletableFuture<String> doSomething1(String id) {
        return CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                System.out.println("doSomething1 execute");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (Exception e) {

                }
                return id;
            }
        });
    }

    public static CompletableFuture<String> doSomething2(String id) {
        return CompletableFuture.supplyAsync(new Supplier<String>() {
            @Override
            public String get() {
                System.out.println("doSomething2 execute");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (Exception e) {

                }
                return id + "doSomething2";
            }
        });
    }
}

package com.xsxy.asynctest.test03;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class Test03CompletableFutureWithException {
    /**
     * 之前的测试completableFuture都是基于流程正常流转,如果出现异常怎么处理
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = new CompletableFuture<>();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
                // 测试异常
                if (true) {
                    throw new RuntimeException("");
                }
                future.complete("complete");
            } catch (Exception e) {
                e.printStackTrace();
                // 先注释掉, 和下边的输出语句同时放开(注释掉32,放开33)
                // future.completeExceptionally(e);
            }


        }, "thread-1").start();

        System.out.println("main");
        System.out.println(future.get());
        // System.out.println(future.exceptionally(t -> "aaaaaa").get());
        System.out.println("main end");
    }
}

猜你喜欢

转载自www.cnblogs.com/nxzblogs/p/12766025.html