每個開發(fā)人員都應(yīng)該了解這些術(shù)語中更深的細微差別
當您說某個特定的框架是"異步","非阻塞"和"事件驅(qū)動"時,請確保使用正確的詞。
當您的同事將某種東西描述為非阻塞的異步I / O時,這意味著什么。 是否可以使用阻塞的異步I / O? 如果不是,非阻塞和異步意味著同一件事嗎? 在本文中,我將解釋這些(以及許多其他)常用(經(jīng)常被濫用)的軟件工程術(shù)語的正確含義和用法。
并發(fā)與并行執(zhí)行并發(fā)-重疊執(zhí)行或時間分片。 并發(fā)是一種編程屬性,即使對于單核計算機也可能發(fā)生。
并行性-同時執(zhí)行。 這是執(zhí)行硬件的屬性,其中任務(wù)實際上同時進行。


同步與AsyncSynchronous-在同步操作的情況下,發(fā)起操作的一方必須等待操作完成。
異步-在異步操作中,啟動器不需要等待操作完成。 它可以繼續(xù)進行下一步,而無需等待對方的結(jié)果。 稍后可以通過其他某種機制來檢測操作的完成。 除了編程,該概念還可以應(yīng)用于其他領(lǐng)域。 電子郵件是異步通信的一個示例,而電話對話是同步的。


阻塞與非阻塞這是一個編程概念,與編寫代碼的方式有關(guān)(與同步與異步不同)。 如果函數(shù)調(diào)用立即返回一個值,則稱為非阻塞。 在某些情況下,例如I / O,功能的邏輯完成結(jié)果無法立即獲得。 但是,它將引用返回到占位符,該值稍后將可用。 例如,Java Future。 即使該值僅在10秒鐘后可用,以下函數(shù)也會立即返回。
- public Future<Integer> calculate(Integer input) {
- return executor.submit(() -> {
- Thread.sleep(10000); return input * input;
- });
- }
異步函數(shù)調(diào)用不能阻塞。
取決于上下文,非阻塞和異步可能意味著相同,也可能不同。 雖然電子郵件通信是異步的,但將電子郵件稱為非阻塞性呼叫并沒有任何意義。
命令式與聲明式編程風格
聲明式編程是一種編程范例,用于表達計算的邏輯(要做什么)而不描述其控制流程(如何做)。 例如SQL命令。
命令式編程是一種編程范式,它根據(jù)更改程序狀態(tài)的語句來描述計算。
下面的示例循環(huán)遍歷數(shù)字1到10,并找到偶數(shù)。
- List<Integer> numbersOneThroughTen = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
- //With imperative programming, we'd step through this, and decide //what we want:
- List<Integer> evenNumbers = new ArrayList<>();
- for (Integer eachValue : numbersOneThroughTen) {
- if (eachValue % 2 == 0) {
- evenNumbers.add(eachValue);
- }
- }
- //The following code uses declarative programming to accomplish the //same thing.
- // Here, we're saying "Give us everything where it's odd"
- evenNumbers = numbersOneThroughTen.stream().filter(num -> num % 2 == 0)
- .collect(Collectors.toList());
注意:這是一個抽象概念。 在上面的示例中,您可以進一步說我們沒有得到" foreach"的實際實現(xiàn),因此從某種意義上說,它是在描述"做什么"而不是"如何做"。 從純粹的命令式到純粹的聲明式,每種編程風格都處在某種范圍內(nèi)。 函數(shù)式編程比過程式編程更具聲明性。
功能編程一種程序設(shè)計范例,其中通過應(yīng)用和組合功能來構(gòu)造程序。 在函數(shù)式編程中,將函數(shù)視為一等公民,這意味著它們可以綁定到名稱(包括本地標識符),作為參數(shù)傳遞并從其他函數(shù)返回,就像任何其他數(shù)據(jù)類型一樣。 這允許程序以聲明性和可組合的方式編寫,其中將小的功能組合在一起以創(chuàng)建更大的功能和程序。 純函數(shù)式編程是所有函數(shù)均為純函數(shù)的函數(shù)式編程的子集。 我將寫另一篇有關(guān)函數(shù)式編程的詳細博客文章。
事件驅(qū)動或基于消息的體系結(jié)構(gòu)事件是系統(tǒng)狀態(tài)的重大變化。 例如,當消費者購買汽車時,汽車的狀態(tài)將從"待售"變?yōu)?quot;已售出"。 汽車經(jīng)銷商的系統(tǒng)體系結(jié)構(gòu)可以將此狀態(tài)更改視為一個事件,該事件的發(fā)生可以被體系結(jié)構(gòu)內(nèi)的其他應(yīng)用程序知道。 嚴格來說,事件無法傳播,只會發(fā)生。 發(fā)出,處理和傳播的實際上是事件的通知-以純文本消息的形式。 在事件驅(qū)動的系統(tǒng)中,不同的參與組件通過異步消息進行通信。
響應(yīng)式系統(tǒng)與響應(yīng)式編程響應(yīng)式系統(tǒng)是一種程序,其體系結(jié)構(gòu)允許它對運行時環(huán)境中的更改做出反應(yīng)。 反應(yīng)性系統(tǒng)(http://www.reactivemanifesto.org)中正式規(guī)定了反應(yīng)性系統(tǒng)應(yīng)具有的屬性。 這些屬性中的三個可以概括為響應(yīng),彈性和彈性。
響應(yīng)式意味著響應(yīng)式系統(tǒng)可以實時響應(yīng)輸入,而不是延遲一個簡單的查詢,因為該系統(tǒng)正在為其他人處理大量工作。
彈性意味著系統(tǒng)通常不會因為一個組件發(fā)生故障而失敗; 斷開的網(wǎng)絡(luò)鏈接不會影響不涉及該鏈接的查詢,對無響應(yīng)組件的查詢可以重新路由到備用組件。
彈性意味著系統(tǒng)可以適應(yīng)其工作負載的變化并繼續(xù)有效執(zhí)行。 由于您可能會在提供食物和提供飲料之間的欄中動態(tài)地重新分配人員,以使兩行的等待時間都相似,因此您可以調(diào)整與各種軟件服務(wù)相關(guān)的工作線程數(shù),以確保沒有工人閑置,同時確保每個隊列繼續(xù) 待處理。
顯然,這些屬性可以通過多種方式實現(xiàn),但是一種主要方法是使用反應(yīng)式編程風格。
響應(yīng)式編程是使用表示為異步消息的事件進行編程(如在事件驅(qū)動的體系結(jié)構(gòu)中)。 這些消息通常被建模為數(shù)據(jù)流。 例如,在Web應(yīng)用程序中,典型的單擊事件可以建模為數(shù)據(jù)流,您可以在該數(shù)據(jù)流上觀察并產(chǎn)生一些副作用。 您可以創(chuàng)建任何數(shù)據(jù)流,而不僅僅是單擊和懸停事件。 流既便宜又無處不在,任何事物都可以是流:變量,用戶輸入,屬性,緩存,數(shù)據(jù)結(jié)構(gòu)等。例如,您的Twitter feed是一種與單擊事件相同的數(shù)據(jù)流。 您可以收聽該流并做出相應(yīng)的反應(yīng)。
流可以用作另一流的輸入。 甚至多個流也可以用作另一個流的輸入。 您可以合并兩個流。 您可以過濾流以獲得另一個只包含您感興趣的事件的流。您可以將數(shù)據(jù)值從一個流映射到另一個新流。