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


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


阻塞與非阻塞這是一個編程概念,與編寫代碼的方式有關(與同步與異步不同)。 如果函數調用立即返回一個值,則稱為非阻塞。 在某些情況下,例如I / O,功能的邏輯完成結果無法立即獲得。 但是,它將引用返回到占位符,該值稍后將可用。 例如,Java Future。 即使該值僅在10秒鐘后可用,以下函數也會立即返回。
- public Future<Integer> calculate(Integer input) {
- return executor.submit(() -> {
- Thread.sleep(10000); return input * input;
- });
- }
異步函數調用不能阻塞。
取決于上下文,非阻塞和異步可能意味著相同,也可能不同。 雖然電子郵件通信是異步的,但將電子郵件稱為非阻塞性呼叫并沒有任何意義。
命令式與聲明式編程風格
聲明式編程是一種編程范例,用于表達計算的邏輯(要做什么)而不描述其控制流程(如何做)。 例如SQL命令。
命令式編程是一種編程范式,它根據更改程序狀態的語句來描述計算。
下面的示例循環遍歷數字1到10,并找到偶數。
- 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"的實際實現,因此從某種意義上說,它是在描述"做什么"而不是"如何做"。 從純粹的命令式到純粹的聲明式,每種編程風格都處在某種范圍內。 函數式編程比過程式編程更具聲明性。
功能編程一種程序設計范例,其中通過應用和組合功能來構造程序。 在函數式編程中,將函數視為一等公民,這意味著它們可以綁定到名稱(包括本地標識符),作為參數傳遞并從其他函數返回,就像任何其他數據類型一樣。 這允許程序以聲明性和可組合的方式編寫,其中將小的功能組合在一起以創建更大的功能和程序。 純函數式編程是所有函數均為純函數的函數式編程的子集。 我將寫另一篇有關函數式編程的詳細博客文章。
事件驅動或基于消息的體系結構事件是系統狀態的重大變化。 例如,當消費者購買汽車時,汽車的狀態將從"待售"變為"已售出"。 汽車經銷商的系統體系結構可以將此狀態更改視為一個事件,該事件的發生可以被體系結構內的其他應用程序知道。 嚴格來說,事件無法傳播,只會發生。 發出,處理和傳播的實際上是事件的通知-以純文本消息的形式。 在事件驅動的系統中,不同的參與組件通過異步消息進行通信。
響應式系統與響應式編程響應式系統是一種程序,其體系結構允許它對運行時環境中的更改做出反應。 反應性系統(http://www.reactivemanifesto.org)中正式規定了反應性系統應具有的屬性。 這些屬性中的三個可以概括為響應,彈性和彈性。
響應式意味著響應式系統可以實時響應輸入,而不是延遲一個簡單的查詢,因為該系統正在為其他人處理大量工作。
彈性意味著系統通常不會因為一個組件發生故障而失敗; 斷開的網絡鏈接不會影響不涉及該鏈接的查詢,對無響應組件的查詢可以重新路由到備用組件。
彈性意味著系統可以適應其工作負載的變化并繼續有效執行。 由于您可能會在提供食物和提供飲料之間的欄中動態地重新分配人員,以使兩行的等待時間都相似,因此您可以調整與各種軟件服務相關的工作線程數,以確保沒有工人閑置,同時確保每個隊列繼續 待處理。
顯然,這些屬性可以通過多種方式實現,但是一種主要方法是使用反應式編程風格。
響應式編程是使用表示為異步消息的事件進行編程(如在事件驅動的體系結構中)。 這些消息通常被建模為數據流。 例如,在Web應用程序中,典型的單擊事件可以建模為數據流,您可以在該數據流上觀察并產生一些副作用。 您可以創建任何數據流,而不僅僅是單擊和懸停事件。 流既便宜又無處不在,任何事物都可以是流:變量,用戶輸入,屬性,緩存,數據結構等。例如,您的Twitter feed是一種與單擊事件相同的數據流。 您可以收聽該流并做出相應的反應。
流可以用作另一流的輸入。 甚至多個流也可以用作另一個流的輸入。 您可以合并兩個流。 您可以過濾流以獲得另一個只包含您感興趣的事件的流。您可以將數據值從一個流映射到另一個新流。