多线程 线程池和异步编排

创建线程的三种方法

继承Thread类

使用时直接new 该实现类然后执行start方法便可以运行线程.

    public void testSearchService() throws ExecutionException, InterruptedException {
        new ThreadTest().start();
    }

    private static class ThreadTest extends Thread {
        @Override
        public void run() {
            System.out.println("开始执行线程.");
            int i = 200 / 10;
            System.out.println(i);
            System.out.println("线程执行结束.");
        }
    }

实现Runable接口

实现Runnable接口并实例化线程类 并将实现Runnable接口的实例对象实例化线程类的构造方法中,之后执行start方法便可以运行线程

    public void testSearchService() throws ExecutionException, InterruptedException {
        new Thread(new RunnableTest()).start();
    }
    private static class RunnableTest implements Runnable {
        @Override
        public void run() {
            System.out.println("开始执行线程.");
            int i = 200 / 10;
            System.out.println(i);
            System.out.println("线程执行结束.");
        }
    }

实现Callable<T>并实现FutureTask获取返回结果

首先实现Runnable接口 范型参数表示返回值类型

    private static class CallableTest implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("开始执行线程.");
            int i = 200 / 10;
            System.out.println(i);
            System.out.println("线程执行结束.");

            return i;
        }
    }

然后实例化FutureTask,并在实例化FuterTask时传入Callable实例化对象, FetureTask的范型参数依旧是返回值类型. 之后实例化线程类并将FetureTask对象传入到线程类构造方法中, 之后执行start方法便可以执行线程, 执行feture.get()可以获取返回值, 如果一直获取不到返回值则会阻塞.

        FutureTask<Integer> futureTask = new FutureTask<>(new CallableTest());

        new Thread(futureTask).start();
        Integer integer = futureTask.get();
        System.out.println(integer);

总结

前两种创建线程无法获取返回值而第三种方法可以和获取返回值
三种方法都无法控制系统资源, 如果线程创建的太多则会导致系统资源耗尽, 这时候就需要线程池了.

线程池

创建线程池需要七个参数
int corePoolSize: 核心线程数, 当创建线程池是一并创建该数目的线程数
int maximumPoolSize: 最大线程数
long keepAliveTime: 空闲时间, 当线程空闲时间到达该数则会被释放, 释放到核心线程数目则不会被释放
TimeUnit unit: 空闲线程时间单位
BlockingQueue workQueue: 空闲任务队列, 根据最大线程数创建线程数已满且线程不是空闲状态, 这时候新进入的任务则会添加到空闲任务队列中.
ArrayBlockingQueue: 基于数组的有界存储队列
DelayQueue: 无边界存储队列
LinkedBlockingDeque: 基于链表的存储队列
LinkedTransferQueue: 基于链表且无界的存储队列
PriorityBlockingQuene: 具有优先级的无界阻塞队列;

ThreadFactory threadFactory 创建线程工厂类
RejectedExecutionHandler handler 线程拒绝策略 当线程池中的任务在执行且空闲任务队列已满 则会根据线程拒绝策略处理该任务
DiscardOldestPolicy: 丢弃最早执行任务 执行当前人物
AbortPolicy: 直接抛出异常
CallerRunsPolicy: 调用run方法来执行当前任务
DiscardPolicy: 直接丢弃最旧任务

    private static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10,
            20,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(100),
            Executors.defaultThreadFactory(),
            new CallerRunsPolicy());

异步编排

CompletableFuture创建异步任务时分为runAsync()代表没有返回值supplyAsync()代表有返回值
当发生异常时会调用whenComplete语句块中的内容 但是不能返回结果

        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程开始执行");
            int i = 200 / 0;
            System.out.println("线程执行完毕");
            return i;
        }).whenComplete((result , e) -> {
            System.out.println(result);
            System.out.println(e);
        }).

如果想要设置返回结果那就得调用exceptionally语句块中的内容 处理异常并设置返回

        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程开始执行");
            int i = 200 / 0;
            System.out.println("线程执行完毕");
            return i;
        }).exceptionally((e) -> {
            System.out.println(e);
            return 10;
        });

根据是否发生异常来分别处理不同的业务可以调用handle语句块如果参数1不为空那么代表没异常 可以正常获取到上一步返回内容, 如果参数2不为空则表示执行出现了异常.

        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程开始执行");
            int i = 200 / 10;
            System.out.println("线程执行完毕");
            return i;
        }).handle((result, exception) -> {
            if (result != null) {
                return result * 100;
            }
            if (exception != null) {
                return 0;
            }

            return 0;
        });

线程串行化

将线程任务以串行的方式进行执行
thenApplyAsync: 获取上一次的执行结果并返回结果值
thenAcceptAsync: 获取上一次返回结果不用返回值
thenRunAsync: 执行下一个任务

        CompletableFuture<Void> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("线程开始执行");
            int i = 200 / 10;
            System.out.println("线程执行完毕");
            return i;
        }).thenApplyAsync((result) -> {
            System.out.println(result);
            return 2000;
        }, threadPool).thenAcceptAsync((result) -> {
            System.out.println(result);
        }, threadPool).thenRunAsync(() -> {
            System.out.println("任务2启动了");
        });

组合两个任务

        // 不获取前两次执行结果 也没有返回内容
        completableFuture01.runAfterBothAsync(completableFuture02, () -> {
            System.out.println("任务3开始执行");
            System.out.println("任务3结束");
        }, threadPool);

        // 获取前两次执行结果 有返回内容
        completableFuture01.thenAcceptBothAsync(completableFuture02, (result1, result2)-> {
            System.out.println("任务3开始执行");
            System.out.println("result1:" + result1);
            System.out.println("result2:" + result2);
            System.out.println("任务3结束");
        }, threadPool);
//
//        // 获取前两次执行结果 并返回内容
        completableFuture01.thenCombineAsync(completableFuture02, (result1, result2) -> {
            System.out.println("任务3开始执行");
            System.out.println("result1:" + result1);
            System.out.println("result2:" + result2);
            System.out.println("任务3结束");
            return result1 + result2;
        }, threadPool);

组合两个任务, 一个任务完成即可立即执行第三个任务

两个任务返回值必须相同

        //  无返回值且 且没有获取任务返回结果
        completableFuture01.runAfterEitherAsync(completableFuture02, () -> {
            System.out.println("任务3开始");
        }, threadPool);


        //  有返回值且 且可以获取任务返回结果
        completableFuture01.applyToEitherAsync(completableFuture02, (result) -> {
            System.out.println("任务3开始");

            return 5500;
        }, threadPool);

        //  无返回值且 且可以获取任务返回结果
        completableFuture01.acceptEitherAsync(completableFuture02, (result) -> {
            System.out.println("任务3开始");

        }, threadPool);

多任务组合

全部任务完成之后再将结果返回

allOf在所有方法执行完毕才会将结果进行返回

        CompletableFuture<String> imgFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("获取商品图片");
            return "lyra.png";
        }, threadPool);

        CompletableFuture<String> nameFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("获取商品名称");
            return "lyra";
        }, threadPool);

        CompletableFuture<Double> priceFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("获取商品价格");
            return 700.00;
      
        }, threadPool);

        CompletableFuture<Void> allCompletableFuture = CompletableFuture.allOf(imgFuture, nameFuture, priceFuture);

        System.out.println(imgFuture.get());
        System.out.println(nameFuture.get());
        System.out.println(priceFuture.get());

任意任务完成立即返回

anyOf只要其中一个任务完成直接将结果进行返回

        CompletableFuture<String> imgFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("获取商品图片");
            return "lyra.png";
        }, threadPool);

        CompletableFuture<String> nameFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("获取商品名称");
            return "lyra";
        }, threadPool);

        CompletableFuture<Double> priceFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("获取商品价格");
            return 700.00;

        }, threadPool);

        CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(imgFuture, nameFuture, priceFuture);

        System.out.println(objectCompletableFuture.get());
posted @   RainbowMagic  阅读(113)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示