国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

強大的CompletableFuture

skinner / 3309人閱讀

摘要:首先想到的是開啟一個新的線程去做某項工作。再進一步,為了讓新線程可以返回一個值,告訴主線程事情做完了,于是乎粉墨登場。然而提供的方式是主線程主動問詢新線程,要是有個回調(diào)函數(shù)就爽了。極大的提高效率。

引子

為了讓程序更加高效,讓CPU最大效率的工作,我們會采用異步編程。首先想到的是開啟一個新的線程去做某項工作。再進一步,為了讓新線程可以返回一個值,告訴主線程事情做完了,于是乎Future粉墨登場。然而Future提供的方式是主線程主動問詢新線程,要是有個回調(diào)函數(shù)就爽了。所以,為了滿足Future的某些遺憾,強大的CompletableFuture隨著Java8一起來了。

Future

傳統(tǒng)多線程的卻讓程序更加高效,畢竟是異步,可以讓CPU充分工作,但這僅限于新開的線程無需你的主線程再費心了。比如你開啟的新線程僅僅是為了計算1+...+n再打印結(jié)果。有時候你需要子線程返回計算結(jié)果,在主線程中進行進一步計算,就需要Future了。

看下面這個例子,主線程計算2+4+6+8+10;子線程計算1+3+5+7+9;最后需要在主線程中將兩部分結(jié)果再相加。

public class OddNumber implements Callable {
    @Override
    public Integer call() throws Exception {
        Thread.sleep(3000);
        int result = 1 + 3 + 5 + 7 + 9;
        return result;
    }
}
public class FutureTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        OddNumber oddNumber = new OddNumber();
        Future future = executor.submit(oddNumber);
        long startTime = System.currentTimeMillis();
        int evenNumber = 2 + 4 + 6 + 8 + 10;
        try {
            Thread.sleep(1000);
            System.out.println("0.開始了:"+ (System.currentTimeMillis()-startTime) +"秒");
            int oddNumberResult = future.get();//這時間會被阻塞
            System.out.println("1+2+...+9+10="+(evenNumber+oddNumberResult));
            System.out.println("1.開始了:"+ (System.currentTimeMillis()-startTime) +"秒");
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
輸出結(jié)果:
0.開始了:1001秒
1+2+...+9+10=55
1.開始了:3002秒

看一下Future接口,只有五個方法比較簡單

//取消任務(wù),如果已經(jīng)完成或者已經(jīng)取消,就返回失敗
boolean cancel(boolean mayInterruptIfRunning);
//查看任務(wù)是否取消
boolean isCancelled();
//查看任務(wù)是否完成
boolean isDone();
//剛才用到了,查看結(jié)果,任務(wù)未完成就一直阻塞
V get() throws InterruptedException, ExecutionException;
//同上,但是加了一個過期時間,防止長時間阻塞,主線程也做不了事情
V get(long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException;
CompletableFuture

上面的看到Future的五個方法,不是很豐富,既然我們的主線程叫做main,就應(yīng)該以我為主,我更希望子線程做完了事情主動通知我。為此,Java8帶來了CompletableFuture,一個Future的實現(xiàn)類。其實CompletableFuture最迷人的地方并不是極大豐富了Future的功能,而是完美結(jié)合了Java8流的新特性。

實現(xiàn)回調(diào),自動后續(xù)操作

提前說一下CompletableFuture實現(xiàn)回調(diào)的方法(之一):thenAccept()

    public CompletableFuture thenAccept(Consumer action) {
        return uniAcceptStage(null, action);
    }

參數(shù)有個Consumer,用到了Java8新特性,行為參數(shù)化,就是參數(shù)不一定是基本類型或者類,也可使是函數(shù)(行為),或者說一個方法(接口)。

public class OddNumberPlus implements Supplier {
    @Override
    public Integer get() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 1+3+5+7+9;
    }
}
public class CompletableFutureTest {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        final int evenNumber = 2 + 4 + 6 + 8 + 10;
        CompletableFuture oddNumber = CompletableFuture.supplyAsync(new OddNumberPlus());
        try {
            Thread.sleep(1000);
            System.out.println("0.開始了:"+ (System.currentTimeMillis()-startTime) +"秒");
            //看這里,實現(xiàn)回調(diào)
            oddNumber.thenAccept(oddNumberResult->
                        {
                            System.out.println("1.開始了:"+ (System.currentTimeMillis()-startTime) +"秒");
                            System.out.println("此時計算結(jié)果為:"+(evenNumber+oddNumberResult));
                        });
            oddNumber.get();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
輸出結(jié)果:
0.開始了:1006秒
1.開始了:3006秒
此時計算結(jié)果為:55

值得一提的是,本例中并沒有顯示的創(chuàng)建任務(wù)連接池,程序會默認選擇一個任務(wù)連接池ForkJoinPool.commonPool()

    private static final Executor asyncPool = useCommonPool ?
        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();

ForkJoinPool始自JDK7,叫做分支/合并框架。可以通過將一個任務(wù)遞歸分成很多分子任務(wù),形成不同的流,進行并行執(zhí)行,同時還伴隨著強大的工作竊取算法。極大的提高效率。當(dāng)然,你也可以自己指定連接池。

CompletableFuture合并

Java8的確豐富了Future實現(xiàn),CompletableFuture有很多方法可供大家使用,但是但從上面的例子來看,其實CompletableFuture能做的功能,貌似Future。畢竟你CompletableFuture用get()這個方法的時候還不是阻塞了,我Future蠻可以自己拿到返回值,再手動執(zhí)行一些操作嘛(雖說這樣main方法一定很不爽)。那么接下來的事情,F(xiàn)uture做起來就十分麻煩了。假設(shè)我們main方法只做奇數(shù)合集加上偶數(shù)合集這一個操作,提前算這兩個合集的操作異步交給兩個子線程,我們需要怎么做呢?沒錯,開啟兩個線程,等到兩個線程都計算結(jié)束的時候,我們進行最后的相加,問題在于,你怎么知道那個子線程最后結(jié)束的呢?(貌似可以做個輪詢,不定的調(diào)用isDone()這個方法...)豐富的CompletableFuture功能為我們提供了一個方法,用于等待兩個子線程都結(jié)束了,再進行相加操作:

    //asyncPool就是上面提到的默認線程池ForkJoinPool
    public  CompletableFuture thenCombineAsync(
        CompletionStage other,
        BiFunction fn) {
        return biApplyStage(asyncPool, other, fn);
    }

看個例子:

public class OddCombine implements Supplier {
    @Override
    public Integer get() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 1+3+5+7+9;
    }
}
public class EvenCombine implements Supplier {
    @Override
    public Integer get() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 2+4+6+8+10;
    }
}
public class CompletableCombineTest {
    public static void main(String[] args) throws Exception{
        CompletableFuture oddNumber = CompletableFuture.supplyAsync(new OddCombine());
        CompletableFuture evenNumber = CompletableFuture.supplyAsync(new EvenCombine());
        long startTime = System.currentTimeMillis();
        CompletableFuture resultFuturn = oddNumber.thenCombine(evenNumber,(odd,even)->{
            return odd + even;
        });
        System.out.println(resultFuturn.get());
        System.out.println("0.開始了:"+ (System.currentTimeMillis()-startTime) +"秒");
    }
}
輸出結(jié)果:
55
0.開始了:3000秒

這邊模擬一個睡1秒,一個睡3秒,但是真正的網(wǎng)絡(luò)請求時間是不定的。是不是很爽,最爽的還不是現(xiàn)象,而是以上操作已經(jīng)利用了Java8流的概念。

兩個子線程還不夠,那么還有anyOff()函數(shù),可以承受多個CompletableFuture,會等待所有任務(wù)都完成。

    public static CompletableFuture allOf(CompletableFuture... cfs) {
        return andTree(cfs, 0, cfs.length - 1);
    }

與它長的很像的,有個方法,是當(dāng)?shù)谝粋€執(zhí)行結(jié)束的時候,就結(jié)束,后面任務(wù)不再等了,可以看作充分條件。

    public static CompletableFuture anyOf(CompletableFuture... cfs) {
        return orTree(cfs, 0, cfs.length - 1);
    }

在上面那個例子的基礎(chǔ)上,把OddNumberPlus類時間調(diào)長一點:

public class OddNumberPlus implements Supplier {
    @Override
    public Integer get() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 1+3+5+7+9;
    }
}
public class CompletableCombineTest {
    public static void main(String[] args) throws Exception{
        CompletableFuture oddNumber = CompletableFuture.supplyAsync(new OddCombine());
        CompletableFuture evenNumber = CompletableFuture.supplyAsync(new EvenCombine());
        CompletableFuture testNumber = CompletableFuture.supplyAsync(new OddNumberPlus());
        long startTime = System.currentTimeMillis();
        CompletableFuture resultFuturn = CompletableFuture.anyOf(oddNumber,evenNumber,testNumber);
        System.out.println(resultFuturn.get());
        System.out.println("0.開始了:"+ (System.currentTimeMillis()-startTime) +"秒");
    }
}
輸出結(jié)果:
30
0.開始了:1000秒
小結(jié)

CompletableFuture的方法其實還有很多,常用的比如說runAsync(),類似于supplyAsync(),只是沒有返回值;除了thenApply()可以加回調(diào)函數(shù)以外,還有thenApply();還有注入runAfterBoth()、runAfterEither(),這些見名知意。還有很多,可以點開CompletableFuture這個類的源碼仔細看一看。見微知著,透過CompletableFuture,更加感覺到Java8的強大,強大的流概念、行為參數(shù)化、高效的并行理念等等,不僅讓Java寫起來更爽,還不斷豐富Java整個生態(tài)。Java一直在進步,所以沒有被時代淘汰,我們Javaer也可以繼續(xù)職業(yè)生涯,感謝Java,一起進步。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75459.html

相關(guān)文章

  • ForkJoin框架之CompletableFuture

    摘要:內(nèi)部類,用于對和異常進行包裝,從而保證對進行只有一次成功。是取消異常,轉(zhuǎn)換后拋出。判斷是否使用的線程池,在中持有該線程池的引用。 前言 近期作者對響應(yīng)式編程越發(fā)感興趣,在內(nèi)部分享JAVA9-12新特性過程中,有兩處特性讓作者深感興趣:1.JAVA9中的JEP266對并發(fā)編程工具的更新,包含發(fā)布訂閱框架Flow和CompletableFuture加強,其中發(fā)布訂閱框架以java.base...

    lindroid 評論0 收藏0
  • 《Java8實戰(zhàn)》-第十一章筆記(CompletableFuture:組合式異步編程)

    摘要:組合式異步編程最近這些年,兩種趨勢不斷地推動我們反思我們設(shè)計軟件的方式。第章中介紹的分支合并框架以及并行流是實現(xiàn)并行處理的寶貴工具它們將一個操作切分為多個子操作,在多個不同的核甚至是機器上并行地執(zhí)行這些子操作。 CompletableFuture:組合式異步編程 最近這些年,兩種趨勢不斷地推動我們反思我們設(shè)計軟件的方式。第一種趨勢和應(yīng)用運行的硬件平臺相關(guān),第二種趨勢與應(yīng)用程序的架構(gòu)相關(guān)...

    hlcfan 評論0 收藏0
  • Java8CompletableFuture進階之道

    摘要:方法接收的是的實例,但是它沒有返回值方法是函數(shù)式接口,無參數(shù),會返回一個結(jié)果這兩個方法是的升級,表示讓任務(wù)在指定的線程池中執(zhí)行,不指定的話,通常任務(wù)是在線程池中執(zhí)行的。該的接口是在線程使用舊的接口,它不允許返回值。 簡介 作為Java 8 Concurrency API改進而引入,本文是CompletableFuture類的功能和用例的介紹。同時在Java 9 也有對Completab...

    SunZhaopeng 評論0 收藏0
  • Java 8 CompletableFuture 教程

    摘要:在這種方式中,主線程不會被阻塞,不需要一直等到子線程完成。主線程可以并行的執(zhí)行其他任務(wù)。如果我們不想等待結(jié)果返回,我們可以把需要等待完成執(zhí)行的邏輯寫入到回調(diào)函數(shù)中。任何立即執(zhí)行完成那就是執(zhí)行在主線程中嘗試刪除測試下。可以使用達成目的。 Java 8 有大量的新特性和增強如 Lambda 表達式,Streams,CompletableFuture等。在本篇文章中我將詳細解釋清楚Compl...

    since1986 評論0 收藏0
  • java8CompletableFuture使用實例

    摘要:這個方法返回與等待所有返回等待多個返回取多個當(dāng)中最快的一個返回等待多個當(dāng)中最快的一個返回二詳解終極指南并發(fā)編程中的風(fēng)格 thenApply(等待并轉(zhuǎn)化future) @Test public void testThen() throws ExecutionException, InterruptedException { CompletableFutur...

    kycool 評論0 收藏0

發(fā)表評論

0條評論

skinner

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<