很有價值的一篇文章,看完你就明白了異步和多線程

大家好,我是躍哥。今天是2.22日,雖然已經工作多天了,但是因爲個人原因,還沒做很好的創作,但是也不能忘記親愛的小夥伴們,所以先來這裏報個到。

大家面試的時候,基本上會遇到說你項目裏哪裏用到了異步,哪裏用到了多線程,能簡單描述下嗎?很多同學可能還不清楚這兩者的區別,今天躍哥就和大家一起重新學習下。

最近在研究Spring Boot中的異步處理,發現涉及到異步和多線程的很多知識點,就先寫幾篇關於異步與多線程的文章,帶大一起回顧或學習一下相關的知識點。下面開始正文內容:

前言

在本文中,我們通過一些通俗易懂的方式來解釋異步編程和多線程編程,然後再介紹一下它們之間的區別。

什麼是異步編程

首先來看一下異步模型。在異步模型中,允許同一時間發生(處理)多個事件。程序調用一個耗時較長的功能(方法)時,它並不會阻塞程序的執行流程,程序會繼續往下執行。當功能執行完畢時,程序能夠獲得執行完畢的消息或能夠訪問到執行的結果(如果有返回值或需要返回值時)。

下面通過一個示例來看一下同步和異步的區別。示例中程序通過網絡獲取兩個文件,並對兩個文件進行合併處理:

異步與同步

上述示例,在異步系統當中的解決方案是開啓一個額外的線程進行處理。第一個線程獲取第一個文件,第二個線程獲取第二個文件,第二個線程並不需要等待第一個線程執行完畢再執行。當兩個線程都獲得到對應的結果之後,再重新同步處理合並結果的操作。

再來看另外一個場景。單線程方法讀取OS(操作系統)當中的文件並需要進行數學運算。而在異步系統中,程序發起讀取OS中文件的請求,由於讀取操作比較耗時,在等待讀取文件時,程序會將控制器返回給CPU進行數學運算。

在異步編程中,通常會針對比較耗時的功能提供一個函數,函數的參數中包含一個額外的參數,用於回調。而這個函數往往稱作回調函數。當比較耗時的功能執行完畢時,通過回調函數將結果返回。關於回調函數相關的知識可參考文章《兩個經典例子讓你徹底理解java回調機制》。

什麼是多線程編程

多線程是指同時併發或並行執行多個指令(線程)。

在單核處理器上,多線程往往會給人程序是在並行執行的錯覺。實際上,處理器是通過調度算法在多線程之間進行切換和調度。或者根據外部輸入(中斷)和線程的優先級的組合來進行線程的切換。

在多核處理器上,線程纔是真正的並行運行。多個處理器同時執行多個線程,以達到更加高效的處理。

一個簡單的示例就是:開啓兩個瀏覽器窗口同時下載兩個文件。每個窗口都使用一個新的線程去下載文件,它們之間並不需要誰等待誰完成,而是並行進行下載。

下圖展示了併發執行多線程應用程序的流程:

多線程執行

異步與多線程的區別

通過上面的介紹,我們可以看出多線程都是關於功能的併發執行。而異步編程是關於函數之間的非阻塞執行,我們可以將異步應用於單線程或多線程當中。

因此,多線程只是異步編程的一種實現形式。

比如,你和你的朋友決定一起做一頓午餐。“異步”就是你對朋友說:“你去商店買意大利麪,回來的時候告訴我一聲,然後一起做午餐。在你買意大利麪的同時,我去準備番茄醬和飲料。”

而“線程”是:“你燒水,我加熱番茄醬。當水燒開了,告訴我,我把意大利放進去。當番茄醬熱了,你可以把奶酪添加進去。當兩者都完成了,就可以坐下來一起喫晚餐。”在線程的示例中,我們可以看到“When,Do”的事件順序,而這些順序代表每個人(線程)的指令集集合的順序。

上述示例可以看出,多線程是與具體的執行者相關的,而異步是與任務相關的。

多線程是程序設計的邏輯層概念,它是進程中併發運行的一段代碼,可以實現線程間的切換執行。

異步和同步是相對的,異步就是彼此獨立,在等待某事件的過程中繼續做自己的事,不需要等待這一事件完成後再工作。

多線程就是實現異步的一個方式。異步是讓調用方法的主線程不需要同步等待另一線程的完成,從而可以讓主線程幹其它的事情。

所以本質上,異步和多線程並不是一個同等關係,異步是最終目的,多線程只是實現異步的一種手段。

如何選擇

面對多線程和異步,我們該如何選擇呢?其實,通常情況下選擇的依據是主要取決於性能。

那麼,同步/異步與單線程/多線程之間的所有組合,哪種模型表現更好?

簡而言之,對於具有大量I/O操作和不同計算的大規模應用程序,使用異步多線程有利於充分利用計算資源,並且能夠照顧到非阻塞函數。這也是所有操作系統所採用的線程模型。

編寫異步操作的複雜程度較高,程序主要使用回調方式進行處理,與正常的思維方式有些出入,而且難以調試。而多線程的使用(濫用)會給系統帶來上下文切換的額外負擔,並且線程間的共享變量可能造成死鎖。

因此在實現這兩種模式時,往往需要處理資源競爭、死鎖、共享資源和回調事件等問題。

小結

在本文中,我們講解了異步編程和多線程編程的定義,然後是它們之間的區別。而本文中的所有術語和概念均與具體技術實現無關。後面我們會繼續講解多線程與異步相關的其他知識點,比如異步調用與回調等。





0、重磅!兩萬字長文總結,梳理 Java 入門進階哪些事(推薦收藏)

1、程序員小躍 2020 原創匯總來襲,全年乾貨一網打盡

2、編程高手是如何練成的?

本文分享自微信公衆號 - 程序員小躍(runningdimple)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章