欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的CompletableFuture詳解

 更新時(shí)間:2023年09月27日 08:32:27   作者:苦?糖?果  
這篇文章主要介紹了Java中的CompletableFuture詳解,Future接口(FutueTask實(shí)現(xiàn)類)定義了操作異步任務(wù)執(zhí)行一些方法,如獲取異步任務(wù)的執(zhí)行結(jié)果、取消任務(wù)的執(zhí)行、判斷任務(wù)是否被取消、判斷任務(wù)執(zhí)行是否完畢等,需要的朋友可以參考下

1.Future

1.1 Future接口理論知識(shí)復(fù)習(xí)

Future接口(FutueTask實(shí)現(xiàn)類)定義了操作異步任務(wù)執(zhí)行一些方法,如獲取異步任務(wù)的執(zhí)行結(jié)果、取消任務(wù)的執(zhí)行、判斷任務(wù)是否被取消、判斷任務(wù)執(zhí)行是否完畢等。 比如主線程讓一個(gè)子線程去執(zhí)行任務(wù),子線程可能比較耗時(shí),啟動(dòng)子線程開(kāi)始執(zhí)行任務(wù)后, 主線程就去做其他事情了,忙其它事情或者先執(zhí)行完,過(guò)了一會(huì)才去獲取子任務(wù)的執(zhí)行結(jié)果或變更的任務(wù)狀態(tài)。

Future接口可以為主線程開(kāi)一個(gè)分支任務(wù),專門為主線程處理耗時(shí)和費(fèi)力的復(fù)雜業(yè)務(wù)。

Future接口能干什么?

Future是Java5新加的一個(gè)接口,它提供了一種異步并行計(jì)算的功能。 如果主線程需要執(zhí)行一個(gè)很耗時(shí)的計(jì)算任務(wù),我們就可以通過(guò)future把這個(gè)任務(wù)放到異步線程中執(zhí)行。主線程繼續(xù)處理其他任務(wù)或者先行結(jié)束,再通過(guò)Future獲取計(jì)算結(jié)果。

代碼說(shuō)話: Runnable接口Callable接口

Future接口和FutureTask實(shí)現(xiàn)類

目的:異步多線程任務(wù)執(zhí)行且返回有結(jié)果,三個(gè)特點(diǎn):多線程/有返回/異步任務(wù)

1.2 FutureTask架構(gòu)

綠色虛線:表示實(shí)現(xiàn)的關(guān)系,實(shí)現(xiàn)一個(gè)接口 綠色實(shí)線:表示接口之間的繼承 藍(lán)色實(shí)線:表示類之間的繼承

1.3 Future編碼實(shí)戰(zhàn)

public class FutureTaskTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        long start = System.currentTimeMillis();
        FutureTask<String> task2 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(2);
            return "2";
        });
        FutureTask<String> task1 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(1);
            return "1";
        });
        FutureTask<String> task3 = new FutureTask<>(() -> {
            TimeUnit.SECONDS.sleep(3);
            return "3";
        });
        executorService.submit(task1);
        executorService.submit(task2);
        executorService.submit(task3);
        System.out.println(task1.get());
        System.out.println(task2.get(3,TimeUnit.SECONDS));
        while (true){
            if(task3.isDone()){
                System.out.println(task3.get());
                break;
            }else {
                TimeUnit.MILLISECONDS.sleep(200);
            }
        }
        System.out.println("執(zhí)行耗時(shí):"+(System.currentTimeMillis()-start));
        executorService.shutdown();
    }
}

1
2
3
執(zhí)行耗時(shí):3066

優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn)

  • future+線程池異步多線程任務(wù)配合,能顯著提高程序的執(zhí)行效率。

缺點(diǎn)

  • 一旦調(diào)用get()方法求結(jié)果,如果計(jì)算沒(méi)有完成容易導(dǎo)致程序阻塞 isDone()輪詢的方式會(huì)耗費(fèi)無(wú)謂的CPU資源,而且也不見(jiàn)得能及時(shí)地得到計(jì)算結(jié)果. 如果想要異步獲取結(jié)果,通常都會(huì)以輪詢的方式去獲取結(jié)果盡量不要阻塞
  • Future對(duì)于結(jié)果的獲取不是很友好,只能通過(guò)阻塞或輪詢的方式得到任務(wù)的結(jié)果。
  • 將多個(gè)異步任務(wù)的計(jì)算結(jié)果組合起來(lái),后一個(gè)異步任務(wù)的計(jì)算結(jié)果需要前一個(gè)異步任務(wù)的值
  • 將兩個(gè)或多個(gè)異步計(jì)算合成一個(gè)異步計(jì)算,這幾個(gè)異步計(jì)算互相獨(dú)立,同時(shí)后面這個(gè)又依賴前一個(gè)處理的結(jié)果。
  • 對(duì)計(jì)算速度選最快:當(dāng)Future集合中某個(gè)任務(wù)最快結(jié)束時(shí),返回結(jié)果,返回第一名處理

對(duì)于簡(jiǎn)單的業(yè)務(wù)場(chǎng)景使用Future完全OK,但想完成上述一些復(fù)雜的任務(wù),使用Future之前提供的那點(diǎn)API就囊中羞澀,處理起來(lái)不夠優(yōu)雅,這時(shí)候還是讓CompletableFuture以聲明式的方式優(yōu)雅的處理這些需求。Future能干的,CompletableFuture都能干。

2. CompletableFuture

2.1 CompletableFuture對(duì)Future的改進(jìn)

CompletableFuture異步線程發(fā)生異常,不會(huì)影響主線程,用來(lái)記錄日志特別方便。

CompletableFuture為什么出現(xiàn) get()方法在Future 計(jì)算完成之前會(huì)一直處在阻塞狀態(tài)下,isDone()方法容易耗費(fèi)CPU資源, 對(duì)于真正的異步處理我們希望是可以通過(guò)傳入回調(diào)函數(shù),在Future結(jié)束時(shí)自動(dòng)調(diào)用該回調(diào)函數(shù),這樣,我們就不用等待結(jié)果。

阻塞的方式和異步編程的設(shè)計(jì)理念相違背,而輪詢的方式會(huì)耗費(fèi)無(wú)謂的CPU資源。因此,JDK8設(shè)計(jì)出CompletableFuture。 CompletableFuture提供了一種觀察者模式類似的機(jī)制,可以讓任務(wù)執(zhí)行完成后通知監(jiān)聽(tīng)的一方。

CompletableFuture和CompletionStage

CompletionStage CompletionStage代表異步計(jì)算過(guò)程中的某一個(gè)階段,一個(gè)階段完成以后可能會(huì)觸發(fā)另外一個(gè)階段 一個(gè)階段的計(jì)算執(zhí)行可以是一個(gè)Function, Consumer或者Runnable。比如: stage.thenApply(x -> square(x)).thenAccept(×->System.out.print(x)).thenRun(( ->systeh.out.println()) 一個(gè)階段的執(zhí)行可能是被單個(gè)階段的完成觸發(fā),也可能是由多個(gè)階段一起觸發(fā) 代表異步計(jì)算過(guò)程中的某一個(gè)階段,一個(gè)階段完成以后可能會(huì)觸發(fā)另外一個(gè)階段,有些類似Linux系統(tǒng)的管道分隔符傳參數(shù)。

CompletableFuture 在Java8中,CompletableFuture提供了非常強(qiáng)大的Future的擴(kuò)展功能,可以幫助我們簡(jiǎn)化異步編程的復(fù)雜性,并且提供了函數(shù)式編程的能力,可以通過(guò)回調(diào)的方式處理計(jì)算結(jié)果,也提供了轉(zhuǎn)換和組合CompletableFuture 的方法。 它可能代表一個(gè)明確完成的Future,也有可能代表一個(gè)完成階段(CompletionStage ),它支持在計(jì)算完成以后觸發(fā)一些函數(shù)或執(zhí)行某些動(dòng)作。 它實(shí)現(xiàn)了Future和CompletionStage接口

核心的四個(gè)靜態(tài)方法,來(lái)創(chuàng)建一個(gè)異步任務(wù)

從Java8開(kāi)始引入了CompletableFuture,它是Future的功能增強(qiáng)版。減少阻塞和輪詢,可以傳入回調(diào)對(duì)象,當(dāng)異步任務(wù)完成或者發(fā)生異常時(shí),自動(dòng)調(diào)用回調(diào)對(duì)象的回調(diào)方法

CompletableFuture的優(yōu)點(diǎn) 異步任務(wù)結(jié)束時(shí),會(huì)自動(dòng)回調(diào)某個(gè)對(duì)象的方法; 主線程設(shè)置好回調(diào)后,不再關(guān)心異步任務(wù)的執(zhí)行,異步任務(wù)之間可以順序執(zhí)行 異步任務(wù)出錯(cuò)時(shí),會(huì)自動(dòng)回調(diào)某個(gè)對(duì)象的方法;

2.2 案例精講

函數(shù)式編程已經(jīng)主流 先說(shuō)說(shuō)join和get對(duì)比 說(shuō)說(shuō)你過(guò)去工作中的項(xiàng)目亮點(diǎn)?大廠業(yè)務(wù)需求說(shuō)明 一波流Java8函數(shù)式編程帶走-比價(jià)案例實(shí)戰(zhàn)

Lambda表達(dá)式+Stream流式調(diào)用+Chain鏈?zhǔn)秸{(diào)用+Java8函數(shù)式編程

案例精講-從電商網(wǎng)站的比價(jià)需求講起

需求說(shuō)明 同一款產(chǎn)品,同時(shí)搜索出同款產(chǎn)品在各大電商平臺(tái)的售價(jià);

輸出返回: 出來(lái)結(jié)果希望是同款產(chǎn)品的在不同地方的價(jià)格清單列表,返回一個(gè)List《mysql》in jd price is 88.05 《mysql》in dangdang price is 86.11 《mysql》in taobao price is 90.43

解決方案,比對(duì)同一個(gè)商品在各個(gè)平臺(tái)上的價(jià)格,要求獲得一個(gè)清單列表,

1 )step by step,按部就班,查完京東查淘寶,查完淘寶查天貓

2 )all in,萬(wàn)箭齊發(fā),一口氣多線程異步任務(wù)同時(shí)查詢

public class CompletableFutureDemo {
    static List<NetMall> list = Arrays.asList(
            new NetMall("vip"),
            new NetMall("jd"),
            new NetMall("tb"),
            new NetMall("pdd")
    );
    public static void main(String[] args) {
        long cur1 = System.currentTimeMillis();
        getPrice("Phone").forEach(r-> System.out.println(r));
        System.out.println("getPrice耗時(shí)"+(System.currentTimeMillis()-cur1));
        long cur2 = System.currentTimeMillis();
        getPriceByCompletableFuture("Phone").forEach(r-> System.out.println(r));
        System.out.println("getPriceByCompletableFuture耗時(shí)"+(System.currentTimeMillis()-cur2));
    }
    private static List<String> getPrice(String productName){
        return list.stream()
                .map(r->String.format(productName+" in %s price is %.2f",r.getName(),r.calcPrice(productName)))
                .collect(Collectors.toList());
    }
    private static List<String> getPriceByCompletableFuture(String productName){
        return list.stream()
                .map(r-> CompletableFuture.supplyAsync(()->String.format(productName+" in %s price is %.2f",r.getName(),r.calcPrice(productName))))
                .collect(Collectors.toList())
                .stream()
                .map(s->s.join())
                .collect(Collectors.toList());
    }
}
class NetMall{
    private String name;
    public double calcPrice(String productName){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return  ThreadLocalRandom.current().nextDouble(100000000)+productName.hashCode();
    }
    public NetMall(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2.3 CompletableFuture常用方法

2.3.1 獲得結(jié)果和觸發(fā)計(jì)算

獲得結(jié)果

public T get() 不見(jiàn)不散
public T get(long timeout,TimeUnit unit) 過(guò)時(shí)不候
public T join()
public T getNow(T valuelfAbsent)

沒(méi)有計(jì)算完成的情況下,給我一個(gè)替代結(jié)果。計(jì)算完,返回計(jì)算完成后的結(jié)果。立即獲取結(jié)果不阻賽。沒(méi)算完,返回設(shè)定 的valuelfAbsent值

主動(dòng)觸發(fā)計(jì)算 public bgolean complete(T value) 是否打斷get方法立即返回括號(hào)值

public class CompletableFutureTest {
  public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
      CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
          try {
              Thread.sleep(2000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          return "hello CompletableFuture";
      });
      System.out.println(completableFuture.getNow("心急吃不了熱豆腐"));
      System.out.println(completableFuture.get());
      System.out.println(completableFuture.get(1500, TimeUnit.MILLISECONDS));
      System.out.println(completableFuture.join());
      System.out.println(completableFuture.complete("未雨綢繆")+"\t"+completableFuture.join());
  }
}

2.3.2 對(duì)計(jì)算結(jié)果進(jìn)行處理

thenApply 計(jì)算結(jié)果存在依賴關(guān)系,這兩個(gè)線程串行化 異常相關(guān):由于存在依賴關(guān)系(當(dāng)前步錯(cuò),不走下一步),當(dāng)前步驟有異常的話就叫停。

public class CompletableFutureTest2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 6;
        },executorService).thenApply((r)-> {
            int i=2/0;
            return r * 5;
        }).thenApply((r)-> {
            System.out.println(r);
            return r - 2;
        }).whenComplete((v, e) -> {
            System.out.println("計(jì)算結(jié)果:"+v);
        }).exceptionally(e -> {
            System.out.println(e.getMessage());
            System.out.println(e);
            return null;
        });
        System.out.println("============主線程==========");
        executorService.shutdown();
    }
}

發(fā)生異常后進(jìn)入exceptionally代碼塊,但是thenApply中的代碼不會(huì)執(zhí)行,whenComplete依舊會(huì)執(zhí)行

============主線程==========
計(jì)算結(jié)果:null
java.lang.ArithmeticException: / by zero
java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero

handle

計(jì)算結(jié)果存在依賴關(guān)系,這兩個(gè)線程串行化 異常相關(guān):有異常也可以往下一步走,根據(jù)帶的異常參數(shù)可以進(jìn)步處理

發(fā)生異常后進(jìn)入exceptionally代碼塊,但是handle和whenComplete依舊會(huì)執(zhí)行

============主線程==========
null
計(jì)算結(jié)果:null
java.lang.NullPointerException
java.util.concurrent.CompletionException: java.lang.NullPointerException

2.3.3 對(duì)計(jì)算結(jié)果進(jìn)行消費(fèi)

接收任務(wù)的處理結(jié)果,并消費(fèi)處理,無(wú)返回結(jié)果thenAccept

public class CompletableFutureTest3 {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(()->{
            return 3;
        }).thenApply(r->{
            return r*8;
        }).thenApply(r->{
            return r/2;
        }).thenAccept(r-> System.out.println(r));
        System.out.println(CompletableFuture.supplyAsync(()->"6666").thenRun(()->{}).join());
        System.out.println(CompletableFuture.supplyAsync(()->"6666").thenAccept(r-> System.out.println(r)).join());
        System.out.println(CompletableFuture.supplyAsync(()->"6666").thenApply(r->r+"9999").join());
    }
}

12
null
6666
null
66669999

completableFuture和線程池說(shuō)明

以thenRun和thenRunAsync為例,有什么區(qū)別?

沒(méi)有傳入自定義線程池,都用默認(rèn)線程池ForkJoinPool; 傳入了一個(gè)自定義線程池, 如果你執(zhí)行第一個(gè)任務(wù)的時(shí)候,傳入了一個(gè)自定義線程池: 調(diào)用thenRun方法執(zhí)行第二個(gè)任務(wù)時(shí),則第二個(gè)任務(wù)和第一個(gè)任務(wù)是共用同一個(gè)線程池。 調(diào)用thenRunAsync執(zhí)行第二個(gè)任務(wù)時(shí),則第一個(gè)任務(wù)使用的是你自己傳入的線程池,第二個(gè)任務(wù)使用的是ForkJoin線程池

有可能處理太快,系統(tǒng)優(yōu)化切換原則,直接使用main線程處理 其它如: thenAccept和thenAcceptAsync,thenApply和thenApplyAsync等,它們之間的區(qū)別也是同理

2.3.4 對(duì)計(jì)算速度進(jìn)行選用與對(duì)計(jì)算結(jié)果進(jìn)行合并

applyToEither:誰(shuí)快用誰(shuí) thenCombine:兩個(gè)completionStage任務(wù)都完成后,最終能把兩個(gè)任務(wù)的結(jié)果一起交給thenCombine來(lái)處理。先完成的先等著,等待其它分支任務(wù)

public class CompletableFutureTest4 {
    public static void main(String[] args) {
        CompletableFuture<String> first = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "1號(hào)選手";
        });
        CompletableFuture<String> second = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "2號(hào)選手";
        });
        CompletableFuture<String> result = first.applyToEither(second, r -> r + "is winner");
        CompletableFuture<String> res = first.thenCombine(second, (x, y) -> x + y);
        System.out.println(result.join());
        System.out.println(res.join());
    }
}

1號(hào)選手is winner
1號(hào)選手2號(hào)選手

到此這篇關(guān)于Java中的CompletableFuture詳解的文章就介紹到這了,更多相關(guān)CompletableFuture詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java靈活使用mysql中json類型字段存儲(chǔ)數(shù)據(jù)詳解

    java靈活使用mysql中json類型字段存儲(chǔ)數(shù)據(jù)詳解

    在數(shù)據(jù)庫(kù)設(shè)計(jì)中,面對(duì)一對(duì)多的關(guān)系,如訂單和商品,可以考慮使用單表存儲(chǔ)而非傳統(tǒng)的分表方式,這篇文章主要介紹了java靈活使用mysql中json類型字段存儲(chǔ)數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2024-09-09
  • 關(guān)于Java8中map()和flatMap()的一些事

    關(guān)于Java8中map()和flatMap()的一些事

    這篇文章主要給大家介紹了關(guān)于Java8中map()和flatMap()的一些事,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 關(guān)于RestTemplate中的Get請(qǐng)求

    關(guān)于RestTemplate中的Get請(qǐng)求

    這篇文章主要介紹了關(guān)于RestTemplate中的Get請(qǐng)求,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 帶你入門Java的類與對(duì)象

    帶你入門Java的類與對(duì)象

    下面小編就為大家?guī)?lái)一篇深入理解Java 對(duì)象和類。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望能給你帶來(lái)幫助
    2021-07-07
  • 解決jmap命令打印JVM堆信息異常的問(wèn)題

    解決jmap命令打印JVM堆信息異常的問(wèn)題

    這篇文章主要介紹了解決jmap命令打印JVM堆信息異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表

    SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表

    這篇文章主要介紹了SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot整合kaptcha驗(yàn)證碼過(guò)程(復(fù)制粘貼即可用)

    SpringBoot整合kaptcha驗(yàn)證碼過(guò)程(復(fù)制粘貼即可用)

    本文介紹了如何在Spring Boot項(xiàng)目中整合Kaptcha驗(yàn)證碼實(shí)現(xiàn),通過(guò)配置和編寫相應(yīng)的Controller、工具類以及前端頁(yè)面,可以生成和驗(yàn)證驗(yàn)證碼,文中指出了在項(xiàng)目結(jié)構(gòu)上的注意事項(xiàng),避免因包結(jié)構(gòu)問(wèn)題導(dǎo)致驗(yàn)證碼無(wú)法顯示
    2025-01-01
  • Spring Data JPA 建立表的聯(lián)合主鍵

    Spring Data JPA 建立表的聯(lián)合主鍵

    這篇文章主要介紹了Spring Data JPA 建立表的聯(lián)合主鍵。本文詳細(xì)的介紹了2種方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-04-04
  • IDEA使用Maven創(chuàng)建module出現(xiàn)Ignored?pom.xml問(wèn)題及解決

    IDEA使用Maven創(chuàng)建module出現(xiàn)Ignored?pom.xml問(wèn)題及解決

    這篇文章主要介紹了IDEA使用Maven創(chuàng)建module出現(xiàn)Ignored?pom.xml問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 基于Java實(shí)現(xiàn)的一層簡(jiǎn)單人工神經(jīng)網(wǎng)絡(luò)算法示例

    基于Java實(shí)現(xiàn)的一層簡(jiǎn)單人工神經(jīng)網(wǎng)絡(luò)算法示例

    這篇文章主要介紹了基于Java實(shí)現(xiàn)的一層簡(jiǎn)單人工神經(jīng)網(wǎng)絡(luò)算法,結(jié)合實(shí)例形式分析了java實(shí)現(xiàn)人工神經(jīng)網(wǎng)絡(luò)的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-12-12

最新評(píng)論