用個小例子來介紹一下JDK8的CompletableFuture
程式碼要解決的問題是:在兩個執行緒裡並行執行任務A和任務B,只要有一個任務完成了,就執行任務C。程式碼如下:
import java.time.LocalTime; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class LearnCompleteFuture { private static Random random = new Random(); public static void main(String[] args) throws InterruptedException, ExecutionException { useFuture(); TimeUnit.SECONDS.sleep(10); System.out.println(); useCompletableFuture(); } private static void useFuture() throws InterruptedException, ExecutionException { System.out.println("Future"); ExecutorService exector = Executors.newFixedThreadPool(3); Future<Void> futureA = exector.submit(() -> work("A1")); Future<Void> futureB = exector.submit(() -> work("B1")); while (true) { try { futureA.get(1, TimeUnit.SECONDS); break; } catch (TimeoutException e) { } try { futureB.get(1, TimeUnit.SECONDS); break; } catch (TimeoutException e) { } } exector.submit(() -> work("C1")).get(); exector.shutdown(); } private static void useCompletableFuture() throws InterruptedException, ExecutionException { System.out.println("CompletableFuture"); CompletableFuture<Void> futureA = CompletableFuture.runAsync(() -> work("A2")); CompletableFuture<Void> futureB = CompletableFuture.runAsync(() -> work("B2")); futureA.runAfterEither(futureB, () -> work("C2")).get(); } public static Void work(String name) { System.out.println(name + " starts at " + LocalTime.now()); try { TimeUnit.SECONDS.sleep(random.nextInt(10)); } catch (InterruptedException e) { } System.out.println(name + " ends at " + LocalTime.now()); return null; } }
兩種方法useFuture和useCompletableFuture相比:
首先,方法2 比 方法1 的程式碼簡單。在方法1裡,既要自己照顧執行緒池的建立和銷燬,還要負責對任務A和任務B的監控。而方法2,只需要用CompletableFuture的runAfterEither就完成了任務A、任務B和任務C之間的依賴關係的定義。
在方法2,甚至用一行程式碼就能完成:
CompletableFuture.runAsync(() -> work("A2")).runAfterEither(CompletableFuture.runAsync(() -> work("B2")), () -> work("C2")).get();
其次,方法2 比 方法1 高效。
方法1的主執行緒,要通過while(true)的方式不斷地輪詢任務A和任務B的執行狀況,浪費CPU資源,而方法2的主執行緒只需要在最後的get()上靜靜地等待任務C的完成。
下面是程式執行的輸出:
從方法1的輸出可以看出,任務C1的開始並不是緊隨著任務A1的完成,差了0.971秒,原因是在方法1裡,是對任務A1和任務B1都用get(1)來詢問他們的狀態,當其中一個任務先完成時,主執行緒可能正阻塞在另一個未完成任務的get上
而方法2完全不存在這樣的問題,任務C2的開始於任務A1的結束之間沒有任何的時間差。
有關CompletableFuture和CompletionStage,同學們應該去翻翻他們的javadoc,他們是jdk8對Fork/Join框架非常重要的貢獻,充分利用能幫助你用簡潔的程式碼就能寫出高效靈活的併發演算法。
留下一個作業題,用CompletableFuture來模擬專案管理裡的甘特圖。
相關推薦
用個小例子來介紹一下JDK8的CompletableFuture
程式碼要解決的問題是:在兩個執行緒裡並行執行任務A和任務B,只要有一個任務完成了,就執行任務C。程式碼如下: import java.time.LocalTime; import java.util.Random; import java.util.concurrent.
M03 利用Accord 進行機器學習的第一個小例子
statistic decide blog cat studio mac eap strong cte 01 安裝 Visual studio 2017. 不具備安裝這個的話,也可安裝,Microsoft Visual Studio Express (or equiva
Sql行轉列的兩個小例子
SQL行轉列 所謂行轉列就是將某一個category型別的列(nx1的矩陣,實質是有m類),目標是將多行轉換成為多列(新增m列)。 例1:模擬順豐SQL小例子 ##順豐面試題(SQLite編碼實現題目) import sqlite3 conn=sqlite3.con
多態的兩個小例子
getclass ava stat new 隱式 static return 應該 多態 class A { public String show(B obj){ return ("A and D"); } public String
RabbitMQ及其.NET客戶端——幾個小例子
一、簡單生產者-消費者(使用direct交換器) 1、生產者 var factory = new ConnectionFactory();//例項化一個工廠 factory.HostName = "localhost"; factory.UserName = "honnnnl";
mysql是我們專案中非常常用的資料型資料庫。但是因為我們需要在資料庫儲存中文字元,所以經常遇到資料庫亂碼情況。下面就來介紹一下如何徹底解決資料庫中文亂碼情況。
mysql是我們專案中非常常用的資料型資料庫。但是因為我們需要在資料庫儲存中文字元,所以經常遇到資料庫亂碼情況。下面就來介紹一下如何徹底解決資料庫中文亂碼情況。 1、中文亂碼 1.1、中文亂碼 create table user(name varchar(11)); # 建立user表
什麼是量子計算機?用一個簡單例子來解釋
譯者:王亮 作者:YK Sugi 原文:http://t.cn/EZAElk0 Hi,大家好! 不久前,我參觀了加拿大溫哥華的D-Wave Systems公司,這是一家制造前沿量子計算機的公司。 我在那裡學到了很多關於量子計算機的知識,所以我寫這篇文章來和大家分享我在那裡所學到的一些知識。
學習c++多型的幾個小例子
//reference: http://blog.csdn.net/hackbuteer1/article/details/7475622 #include<iostream> #include<string> #include <vect
python的迴圈——幾個小例子
1、整數序列求和。使用者輸入一個正整數N,計算從1到N(包含1和N)相加之後的結果。 2、九九乘法表輸出。 3、階乘計算。計算1+2!+3!+……10!的結果 4、健康食譜輸出。列出5種不同的食材,請輸出他們可能組成的所
從一個小例子來初步認識遞迴,迭代,動態規劃。
問題:有n步臺階,一次只能上1步或者2步,共有多少種走法? 思路: a 遞迴 步驟1:找到走完前n步臺階和前n-1步臺階之間的關係。 為了走上n步臺階,只有兩種方法:從n-1步臺階爬1步走到或從n-2步臺階處爬兩步走到。如果f(n)是爬到第n臺階的方法數,則f(n) = f
讓我們用貨幣的眼光來分析一下比特幣
'我們實際上建造了這個在過去二三百年我麼生活於其中的世界,我們犯下了一些錯誤,我們學習,為了讓世界變得更好,在我看來,那種觀點認為(比特幣)是金鑰匙,只要我們不再做一些事情,完美的秩序就將會出現,這種觀點是幼稚的,是思想上的迷惑,這在我看來,但是這並不是說比特幣不是一個令人興奮的東西,比特幣
工廠模式個人寫個小例子進行總結
工廠模式是我們最常用的例項化物件模式了,是用工廠方法代替new操作的一種模式。著名的Jive論壇 ,就大量使用了工廠模式,工廠模式在Java程式系統可以說是隨處可見。因為工廠模式就相當於建立例項物件的
使用Dagger2建立的第一個小例子
將Dagger系列的咖啡壺例子再做一下簡化,作為Dagger2的入門的第一個小例子。 場景描述:有一個電水壺,它使用一個加熱器來燒水。電水壺具備的功能有:開始加熱(on方法),結束加熱(off方法),倒水(brew方法)。 正確使用Dagger2要按照以下5個步驟來進行:
幾個小例子--memory leak
C++程式設計師最害怕、最容易遇到的問題就是記憶體洩露,或是說非法訪問記憶體。 不想說太多的道理,就用幾個簡單的例子來詮釋。 指標超過作用域 void MemoryLeak( ) { int
ruby+selenium-webdriver一步一步完成自動化測試-----第一個小例子
第一個小例子,登入soso首頁,簡單直觀易懂。通常我們都是這樣寫的,網上各種例子也是這樣的。 1.開啟文字編輯器SciTe2.file--new新建一個檔案,寫下如下程式碼 #encoding: utf-8 require 'rubygems' require 'sele
用生動的例子來解釋卷積
前言 學了幾周的深度學習,前幾天感覺基礎不太牢固,於是今天便從卷積神經網路開始複習,把腦子中不太清楚的概念全部弄清楚。先在這裡說清楚,本文大部分例子都是參考其他的部落格,在某些例子中有些許改動,穿插著我自己的理解。 1. 從捲毛巾開始理解卷積 首先看看卷積的定義
Java繼承的兩個小例子
首先上程式碼 public class A { protected String value = "123"; public A(){ System.out.println("A"); } public String get
Socket 單執行緒多使用者併發的兩個小例子
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include
試試 IEnumerable 的 10 個小例子
IEnumerable 介面是 C# 開發過程中非常重要的介面,對於其特性和用法的瞭解是十分必要的。本文將通過10個小例子,來熟悉一下其簡單的用法。 全是原始碼 以下便是這10個小例子,響應的說明均標記在註釋中。 每個以 TXX 開頭命名的均是一個示例。建議從上往下閱讀。 using System; usi
試試 IEnumerable 的另外 6 個小例子
IEnumerable 介面是 C# 開發過程中非常重要的介面,對於其特性和用法的瞭解是十分必要的。本文將通過6個小例子,來熟悉一