• JUC——并发编程—第三部分


    四大函数式接口(必须掌握)

    函数式接口:只有一个方法的接口

    1. @FunctionalInterface
    2. public interface Runnable {
    3. public abstract void run();
    4. }
    5. //简化编程模型,在新版本的框架底层大量应用
    6. //foreach(消费者的函数式接口)

    Function接口(函数型接口)

    1. /**
    2. * Function 函数型接口,有一个输入参数,有一个输出
    3. * 只要是函数型接口,可以用lambda表达式简化
    4. */
    5. public class demo01 {
    6. public static void main(String[] args) {
    7. // Function function=new Function(){
    8. // @Override
    9. // public String apply(String o) {
    10. // return o;
    11. // }
    12. // };
    13. Function function=(str)->{
    14. return str;
    15. };
    16. System.out.println(function.apply("asd"));
    17. }
    18. }

    Preddicate接口(断定型接口)

    1. /**
    2. * 断定型接口: 有一个输入参数,返回值只能是布尔值!
    3. */
    4. public class Demo02 {
    5. public static void main(String[] args) {
    6. // Predicate predicate=new Predicate() {
    7. // @Override
    8. // public boolean test(String o) {
    9. // if(o.isEmpty())
    10. // {
    11. // return true;
    12. // }
    13. // return false;
    14. // }
    15. // };
    16. Predicate predicate=(str)->{
    17. return str.isEmpty();
    18. };
    19. System.out.println(predicate.test("123"));
    20. }
    21. }

    Consumer消费型接口

    1. /**
    2. * Consumer 消费型接口:只有输入,没有返回值
    3. */
    4. public class demo03 {
    5. public static void main(String[] args) {
    6. // Consumer consumer = new Consumer(){
    7. // @Override
    8. // public void accept(String s) {
    9. // System.out.println(s);
    10. // }
    11. // };
    12. Consumer consumer=(s)->{
    13. System.out.println(s);
    14. };
    15. consumer.accept("yhy");
    16. }
    17. }

    Supplier供给型接口

    1. /**
    2. * Suppiler 没有参数,只有返回值
    3. */
    4. public class demo04 {
    5. public static void main(String[] args) {
    6. // Supplier supplier=new Supplier() {
    7. // @Override
    8. // public String get() {
    9. // return "114514";
    10. // }
    11. // };
    12. Supplier supplier=()->{
    13. return "114514";
    14. };
    15. System.out.println(supplier.get());
    16. }
    17. }

    Stream流式计算

    集合,MySQL本质都是存储东西。计算交给流来操作。

    在这个接口有如下方法

     

    等等这些方法都是函数式接口。 

    1. public class Test {
    2. public static void main(String[] args) {
    3. User u1=new User(1,"a",21);
    4. User u2=new User(2,"b",22);
    5. User u3=new User(3,"c",23);
    6. User u4=new User(4,"d",24);
    7. User u5=new User(5,"e",25);
    8. User u6=new User(6,"g",26);
    9. //集合存储
    10. List list= Arrays.asList(u1,u2,u3,u4,u5,u6);
    11. //计算交给Stream流
    12. //Lambda表达式、链式编程、函数式接口、Stream流式计算
    13. list.stream()
    14. .filter(u->{return u.getId()%2==0;})
    15. .filter(u->{return u.getAge()>23;})
    16. .map(u->{return u.getName().toUpperCase();})
    17. .sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
    18. .limit(1)
    19. .forEach(System.out::println);
    20. }
    21. }

    Forkjoin(分支合并)

    在jdk1.7,并行执行任务!提高效率。大数据量!

    大数据:Map Reduce(把大任务拆分为小任务)

    Forkjoin特点:工作窃取

    里面维护的都是双端队列

    两个线程执行任务,一个提前完成了就会去执行另一个的任务。


    1. /**
    2. * 求和计算任务
    3. * 3000 6000(forkjoin) 9000(Stream并行流)
    4. * //如何使用Forkjoin
    5. * //1.forkjoinpool
    6. * //2.计算任务forkjointaskPool.execute(ForkJoinTasktask)
    7. * //3.计算类继承RecursiveTask
    8. */
    9. public class ForkJoin extends RecursiveTask {
    10. private Long start;
    11. private Long end;
    12. private Long temp=10000L;
    13. public ForkJoin(Long start, Long end) {
    14. this.start = start;
    15. this.end = end;
    16. }
    17. @Override
    18. protected Long compute() {
    19. if((end-start)
    20. Long sum = 0L;
    21. for(int i=0;i<10_0000_0000;i++)
    22. {
    23. sum+=i;
    24. }
    25. return sum;
    26. }else{
    27. //分支合并计算
    28. Long middle=(start+end)/2;//中间值
    29. ForkJoin task1=new ForkJoin(start,middle);
    30. task1.fork();//拆分任务,将任务压入线程队列。
    31. ForkJoin task2=new ForkJoin(middle+1,end);
    32. task2.fork();//拆分任务,将任务压入线程队列。
    33. return task1.join()+task2.join();
    34. }
    35. }
    36. }

     这个玩意本质上就是的二分+递归,很简单的算法。

    每二分一次线程数+1;各个线程执行不同段的计算任务。

    1. /**
    2. * 3000 6000(forkjoin) 9000(Stream并行流)
    3. */
    4. public class Test {
    5. public static void main(String[] args) throws ExecutionException, InterruptedException {
    6. // test1(); //sum-243309312时间:9346
    7. // test2(); //8088?????? 好像也没快多少
    8. test3(); //700 究极快,最大限度利用CPU
    9. }
    10. public static void test1(){
    11. long start =System.currentTimeMillis();
    12. Long sum=0L;
    13. for(Long i=1L;i<=10_0000_0000;i++){
    14. sum+=i;
    15. }
    16. long end=System.currentTimeMillis();
    17. System.out.println("sum"+sum+"时间:"+(end-start));
    18. }
    19. //使用forkjoin
    20. public static void test2() throws ExecutionException, InterruptedException {
    21. long start =System.currentTimeMillis();
    22. ForkJoinPool forkJoinPool = new ForkJoinPool();
    23. ForkJoinTask forkJoin = new ForkJoin(0L, 10_0000_0000L);
    24. ForkJoinTask submit=forkJoinPool.submit(forkJoin);//提交任务,有结果
    25. Long sum=submit.get();
    26. //forkJoinPool.execute(forkJoin);//执行,没有结果
    27. long end=System.currentTimeMillis();
    28. System.out.println("sum"+sum+"时间:"+(end-start));
    29. }
    30. //使用stream并行流
    31. public static void test3(){
    32. long start =System.currentTimeMillis();
    33. //(]
    34. LongStream.rangeClosed(0L,10_0000_0000L).parallel().reduce(0,Long::sum);
    35. long end=System.currentTimeMillis();
    36. System.out.println("sum"+"时间:"+(end-start));
    37. }
    38. }

    异步回调(Future接口)

    Future接口设计的初衷:对将来的事件进行建模。

    前后端异步通信有ajax,java中也有异步通信。

     

    1. /**
    2. * 异步调用: CompltableFuture
    3. * //异步调用
    4. * //成功回调
    5. * //失败回调
    6. */
    7. public class demo01 {
    8. public static void main(String[] args) throws ExecutionException, InterruptedException {
    9. // //没有返回值的异步回调
    10. // CompletableFuture completedFuture = CompletableFuture.runAsync(()->{
    11. // try {
    12. // TimeUnit.SECONDS.sleep(2);
    13. // } catch (InterruptedException e) {
    14. // throw new RuntimeException(e);
    15. // }
    16. // System.out.println(Thread.currentThread().getName()+"runAsync=>void");
    17. // });
    18. // System.out.println("11111");
    19. // completedFuture.get(); //阻塞获取执行结果
    20. // System.out.println("22222");
    21. //有返回值的异步回调
    22. //ajax,成功和失败的回调
    23. //返回的是错误信息
    24. CompletableFuture completedFuture =CompletableFuture.supplyAsync(()->{
    25. System.out.println(Thread.currentThread().getName()+" runAsync=>void");
    26. int t=10/0;
    27. return 1024;
    28. });
    29. System.out.println(completedFuture.whenComplete((t, u) -> {
    30. System.out.println("t=>"+t); //正常的返回结果
    31. System.out.println("u=>"+u); //抛出的错误信息
    32. }).exceptionally((e) -> {
    33. System.out.println(e.getMessage());//获取报错信息
    34. return 233; //获取到错误的返回结果
    35. }).get());
    36. }
    37. }
    1. whenComplete(...)方法在CompletableFuture正常完成或遇到异常时均能执行。它接收两个参数,第一个参数是正常返回的结果(如果有),第二个参数是抛出的异常(如果有)。所以,这个方法中的输出语句会在CompletableFuture正常完成或遇到异常时都执行。

    2. exceptionally(...)方法是用于处理异常情况的。如果CompletableFuture遇到异常,exceptionally(...)方法会被触发,并且它返回一个备用的结果。在你的代码中,exceptionally(...)方法中的代码会捕获到supplyAsync(...)中的异常(因为你在supplyAsync(...)中除以0了),然后输出异常信息并返回一个备用的结果(233)。因此,这个方法会执行,并输出异常信息。

    综上所述,这句输出语句会执行是因为whenComplete(...)方法在正常或异常完成时都会执行,而exceptionally(...)方法会捕获异常并处理它,然后返回备用结果。

  • 相关阅读:
    C++ 实现2048小游戏
    海马算法 (Sea-Horse optimizer ,SHO)附matlab代码
    C++STL---Vector、List所要掌握的基本知识
    威纶通触摸屏的配方功能具体使用方法介绍(宏指令写入PLC)
    独立站有哪些选品技巧
    Pandas数据清洗_Python数据分析与可视化
    XML 解析技术:DOM4j
    linux虚拟文件系统
    Llama 3 开源了「GitHub 热点速览」
    mac本地安装PHP redis扩展
  • 原文地址:https://blog.csdn.net/m0_62327332/article/details/133468369