首页 > 编程语言 >JUC并发编程基础篇第二章之CompletableFuture[加强版的线程]

JUC并发编程基础篇第二章之CompletableFuture[加强版的线程]

时间:2023-04-07 15:47:57浏览次数:45  
标签:JUC return 加强版 System CompletableFuture println executorService out

@

目录

1、 创建线程的几种方式

new thread:

        //构造方法给指定的线程指定名称,推荐
        Thread thread = new Thread(t1) {
            @Override
            public void run() {
                //要执行的任务
            }
        };
        //启动线程
        thread.start();

new runnable:

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                //要执行的任务
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();

Future

        FutureTask<Integer> task = new FutureTask<>(() -> {
            System.out.println(执行的任务);
            return 100;
        });
        new Thread(task,t1).start();
        Integer integer = task.get();
        System.out.println(结果是+integer);

2、 Future的优缺点

优点: Future配合线程池能够显著提高程序的执行效率

public static void main(String[] args) throws ExecutionException, InterruptedException {
        long startTime = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        FutureTask<String> stringFutureTask1 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(5);
            return over;
        });
        executorService.submit(stringFutureTask1);


        FutureTask<String> stringFutureTask2 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(3);
            return over;
        });
        executorService.submit(stringFutureTask2);

        FutureTask<String> stringFutureTask3 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(3);
            return over;
        });
        executorService.submit(stringFutureTask3);
        System.out.println(stringFutureTask1.get());
        System.out.println(stringFutureTask2.get());
        System.out.println(stringFutureTask3.get());
        executorService.shutdown();
        long endTime = System.currentTimeMillis();
        System.out.println(耗时了+(endTime-startTime));
    }

输出结果:

over

over

over

耗时了5084

可以看到如果是串行输出,结果是5s+3s+3s的耗时;


  • 缺点1:Get 方法容易导致堵塞

从上面的程序,我必须得到stringFutureTask1 执行完后,主线程才能执行任务, 输出耗时时间,我们的期望是 stringFutureTask1在耗时5s的时间内,主线程忙其他事情, 并询问下stringFutureTask1 是否执行完毕, 如果执行完毕,则输出耗时时间;

  • 缺点2:Get 方法没有最大等待时间

比如我们最多只能等待5s, 但是如果get()方法执行10s的话, 则会影响我们的程序

  • 缺点3: isDone 容易导致cpu轮训空转
   public static void main(String[] args) throws ExecutionException, InterruptedException {
        long startTime = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        FutureTask<String> stringFutureTask1 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(5);
            return over;
        });
        executorService.submit(stringFutureTask1);
        executorService.shutdown();

        while (true) {
            if (stringFutureTask1.isDone()){
                long endTime = System.currentTimeMillis();
                System.out.println(耗时了 + (endTime - startTime));
            }
        }
    }

3、CompletableFuture对Future的改进

对于真正的异步处理我们希望可以通过传入回调函数,在Future结束时自动调用该函数;这样我们就不用等待结果了;

3.1、CompletableFuture的基本结构

public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
  • CompletionStage 代表计算过程的一个阶段,一个阶段完成以后可能会触发另一个阶段;

  • 一个阶段的计算,可以是一个function,consumer或者runnable. 比如stage.thenApply(x->square(x)).thenAccept(x->system.out.print(x)).thenReturn(()->system.out.println())

  • 一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发;

3.2、创建CompletableFuture四种方式

  • runAsync 无返回值
返回值 具体方法
static CompletableFuture runAsync(Runnable runnable)
static CompletableFuture runAsync(Runnable runnable, Executor executor)

代码示例

public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },executorService);
        System.out.println(voidCompletableFuture.get());
    }
  • supplyAsync有返回值
返回值 具体方法
static CompletableFuture supplyAsync(Supplier supplier)
static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
 public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return over;
        }, executorService);
        System.out.println(stringCompletableFuture.get());<br></br>        System.out.println(stringCompletableFuture.jion());
    }

输出结果
pool-1-thread-1
over
  • 指的注意的是,join方法和get方法,都可以获取返回值,而join没有处理异常而已;他不会要求抛出异常

3.3、CompletableFuture的流式调用

public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return over;
        }, executorService).whenComplete((v, e) -> {
            System.out.println(hello +v);
            if (e == null) {
                System.out.println(没有异常,更新完成);
            }
        }).exceptionally(s -> {
            s.printStackTrace();
            System.out.println(异常了,主线程先忙其他事情);
            return null;
        });
        System.out.println(主线程工作);
    }

扩展: 函数值编程接口

3.4、CompletableFuture常见的用法

对计算结果进行合并

public static void main(String[] args) throws Exception {
        CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> {
            return 1;
        });
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            return 10;
        });

        CompletableFuture<Integer> integerCompletableFuture = task1.thenCombine(task2, (x, y) -> {
            return x + y;
        });
        System.out.println(integerCompletableFuture.get());
    }

标签:JUC,return,加强版,System,CompletableFuture,println,executorService,out
From: https://www.cnblogs.com/itcastwzp/p/17296369.html

相关文章

  • JUC并发编程基础篇第三章之Synchronized八锁案例[理解锁的对象]
    目录1、总结2、Java8锁案例1打印的方法都有synchronized修饰,先调用email,后调用Sms;输出顺序?案例2如果在发送email的方法,加入了暂定3s中的操作,打印顺序?案例3增加一个普通的方法hello,此时b线程调用hello,先打印email还是hello?案例4有两部手机,先打印邮件还是短信案......
  • JUC并发编程基础篇第四章之公平锁/重入锁/死锁[常见锁的基本认识]
    @目录1、公平锁/非公平锁1.1、概念1.2、非公平锁代码案例1.3、公平锁代码案例1.4、面试题:为什么会有这样的公平锁和非公所这样的设计2、重入锁2.1、简介2.2、没有重入锁,会发生什么问题2.3、可重入锁的种类2.3.1、隐式锁2.3.2、显式锁2.4、面试题:可重入锁的实现机制3、死锁3.1......
  • JUC并发编程基础篇第六章之LockSupport[notify,signal之外的另一种唤醒方式]
    目录1、LockSupport有什么用2、使用wait和notify唤醒一个线程2.1、正常情况2.2、异常情况2,这里去掉了synchronized(o){}代码块2.3、异常情况3先notify再wait3、使用await和signal唤醒一个线程3.1、正常情况3.2、异常情况:如果去除锁块3.3、异常情况:先执行signal......
  • JUC并发编程基础篇第五章之线程中断状态[你理解的线程中断,只会Thread.interrupted()
    目录1、什么是线程的中断机制2、isterruptinterruptedisInterrupted区别3、面试题3.1、如何停止中断运行中的线程3.2、当前线程的中断标识符为true,是不是线程就立马停止了3.3、如果线程处于被阻塞的状态(列入sleep,wait,join等状态),在别的线程调用当前线程的interrupt()方法,会发生......
  • GMOI R2 T2 猫耳小(加强版) 官方题解
    首先特判\(k=0\)的情况,此时的答案为非\(0\)数的个数,改法是将它们全改成\(0\)。再特判\(k\)较大的情况,此时的答案为\(0\)。否则,对于\(k\)大小适中的情况,我们从前往后遍历数组,同时维护当前区间的\(\operatorname{mex}\)值。根据\(\operatorname{mex}\)的定义,显然对......
  • 【Java 并发】【九】【AQS】【一】什么是AQS?为什么说它是JUC基础框架?
    1 前言这节我们来开始看AQS,这个东西可以说是搞Java的都知道的,本节会介绍一下AQS以及它提供的基本机制,后面再对AQS提供的每一个机制一个个深入的剖析。2  什么是AQS?(同步器基础框架)AQS叫做抽象队列同步器(AbstractQueuedSynchronizer),它是一个实现了同步器功能的基础框架,其......
  • 记几次 [线上环境] Dubbo 线程池占满原因分析(第二次:CompletableFuture)
    转载:https://blog.csdn.net/wsmalltiger/article/details/124236189文章目录[线上环境]Dubbo线程池占满原因排查系列前言一、问题分析1、分析日志2、定位原因二、解决方案三、总结前言  某天早上9点左右收到线上故障报警,超过3个商家反馈“无法正常进入功能页面,点击相关操作提......
  • 并发编程——JUC并发大厂面试问题
    摘要现如今,不管是应届毕业生还是工作了三五年之内的工程师,在面试招聘的时候JUC并发编程的是必须掌握的一个技能,否者你将会被面试官玩弄。本博文将整理有关于的JUC的大厂面试问题和答案。帮助大家在面试过程中能够回答面试官问题的一二。同时本人也总结相关的面试问题的在相关文档中......
  • 【Java 并发】【八】【Atomic】【一】JUC下的Atomic原子类体系概览
    1 前言这节我们就开始看看Atomic原子类系列,JUC包下提供的原子类底层的实现原理基本都是差不多的,都是基于volatile和CAS操作来保证线程安全的,我们后续会着重分析几个类。2  概览我们看下JUC下边都有哪些原子类:看上面的图形,我们使用红色圈中的那些,就是我们要着重讨论的,一共......
  • 加强版Google Glass:能够预知未来的视网膜成像技术(视频)
    曾经,人们的头脑中有这样一种观念,预测未来几乎是件不可能的事情。但是随着科技的发展,我们已经渐渐从之前的思维中走了出来,未来惊悚片《少数派报告》(MinorityReport)就是一个很好的例子,这部电影向什么传达了这样一种概念:未来是可以预知的。虽然《少数派报告》只是一部娱乐大众的科......