摘要:異步調(diào)用異步調(diào)用是為了解決同步調(diào)用可能出現(xiàn)阻塞,導(dǎo)致整個流程卡住而產(chǎn)生的一種調(diào)用方式?;卣{(diào)是一種思想是一種機制,至于具體如何實現(xiàn),如何通過代碼將回調(diào)實現(xiàn)得優(yōu)雅實現(xiàn)得可擴展性比較高,一看開發(fā)者的個人水平,二看開發(fā)者對業(yè)務(wù)的理解程度。
模塊間調(diào)用
在一個應(yīng)用系統(tǒng)中,無論使用何種語言開發(fā),必然存在模塊之間的調(diào)用,調(diào)用的方式分為幾種:
(1)同步調(diào)用
同步調(diào)用是最基本并且最簡單的一種調(diào)用方式,類A的方法a()調(diào)用類B的方法b(),一直等待b()方法執(zhí)行完畢,a()方法繼續(xù)往下走。這種調(diào)用方式適用于方法b()執(zhí)行時間不長的情況,因為b()方法執(zhí)行時間一長或者直接阻塞的話,a()方法的余下代碼是無法執(zhí)行下去的,這樣會造成整個流程的阻塞。
(2)異步調(diào)用
異步調(diào)用是為了解決同步調(diào)用可能出現(xiàn)阻塞,導(dǎo)致整個流程卡住而產(chǎn)生的一種調(diào)用方式。類A的方法方法a()通過新起線程的方式調(diào)用類B的方法b(),代碼接著直接往下執(zhí)行,這樣無論方法b()執(zhí)行時間多久,都不會阻塞住方法a()的執(zhí)行。但是這種方式,由于方法a()不等待方法b()的執(zhí)行完成,在方法a()需要方法b()執(zhí)行結(jié)果的情況下(視具體業(yè)務(wù)而定,有些業(yè)務(wù)比如啟異步線程發(fā)個微信通知、刷新一個緩存這種就沒必要),必須通過一定的方式對方法b()的執(zhí)行結(jié)果進行監(jiān)聽。在Java中,可以使用Future+Callable的方式做到這一點.
(3)回調(diào)
最后是回調(diào),回調(diào)的思想是:
類A的a()方法調(diào)用類B的b()方法
類B的b()方法執(zhí)行完畢主動調(diào)用類A的callback()方法
這樣一種調(diào)用方式組成了上圖,也就是一種雙向的調(diào)用方式。
代碼示例
接下來看一下回調(diào)的代碼示例,代碼模擬的是這樣一種場景:老師問學(xué)生問題,學(xué)生思考完畢回答老師。
首先定義一個回調(diào)接口,只有一個方法tellAnswer(int answer),即學(xué)生思考完畢告訴老師答案:
1 /** 2 * 回調(diào)接口,原文出處http://www.cnblogs.com/xrq730/p/6424471.html 3 */ 4 public interface Callback { 5 6 public void tellAnswer(int answer); 7 8 }
定義一個老師對象,實現(xiàn)Callback接口:
1 /** 2 * 老師對象,原文出處http://www.cnblogs.com/xrq730/p/6424471.html 3 */ 4 public class Teacher implements Callback { 5 6 private Student student; 7 8 public Teacher(Student student) { 9 this.student = student; 10 } 11 12 public void askQuestion() { 13 student.resolveQuestion(this); 14 } 15 16 @Override 17 public void tellAnswer(int answer) { 18 System.out.println("知道了,你的答案是" + answer); 19 } 20 21 }
老師對象有兩個public方法:
(1)回調(diào)接口tellAnswer(int answer),即學(xué)生回答完畢問題之后,老師要做的事情
(2)問問題方法askQuestion(),即向?qū)W生問問題
接著定義一個學(xué)生接口,學(xué)生當然是解決問題,但是接收一個Callback參數(shù),這樣學(xué)生就知道解決完畢問題向誰報告:
1 /** 2 * 學(xué)生接口,原文出處http://www.cnblogs.com/xrq730/p/6424471.html 3 */ 4 public interface Student { 5 6 public void resolveQuestion(Callback callback); 7 8 }
最后定義一個具體的學(xué)生叫Ricky:
1 /** 2 * 一個名叫Ricky的同學(xué)解決老師提出的問題,原文出處http://www.cnblogs.com/xrq730/p/6424471.html 3 */ 4 public class Ricky implements Student { 5 6 @Override 7 public void resolveQuestion(Callback callback) { 8 // 模擬解決問題 9 try { 10 Thread.sleep(3000); 11 } catch (InterruptedException e) { 12 13 } 14 15 // 回調(diào),告訴老師作業(yè)寫了多久 16 callback.tellAnswer(3); 17 } 18 19 }
在解決完畢問題之后,第16行向老師報告答案。
寫一個測試類,比較簡單:
1 /** 2 * 回調(diào)測試,原文出處http://www.cnblogs.com/xrq730/p/6424471.html 3 */ 4 public class CallbackTest { 5 6 @Test 7 public void testCallback() { 8 Student student = new Ricky(); 9 Teacher teacher = new Teacher(student); 10 11 teacher.askQuestion(); 12 13 } 14 15 }
代碼運行結(jié)果就一行:
知道了,你的答案是3
簡單總結(jié)、分析一下這個例子就是:
(1)老師調(diào)用學(xué)生接口的方法resolveQuestion,向?qū)W生提問
(2)學(xué)生解決完畢問題之后調(diào)用老師的回調(diào)方法tellAnswer
這樣一套流程,構(gòu)成了一種雙向調(diào)用的關(guān)系。
代碼分析
分析一下上面的代碼,上面的代碼我這里做了兩層的抽象:
(1)將老師進行抽象
將老師進行抽象之后,對于學(xué)生來說,就不需要關(guān)心到底是哪位老師詢問我問題,只要我根據(jù)詢問的問題,得出答案,然后告訴提問的老師就可以了,即使老師換了一茬又一茬,對我學(xué)生而言都是沒有任何影響的
(2)將學(xué)生進行抽象
將學(xué)生進行抽象之后,對于老師這邊來說就非常靈活,因為老師未必對一個學(xué)生進行提問,可能同時對Ricky、Jack、Lucy三個學(xué)生進行提問,這樣就可以將成員變量Student改為List
這個例子是一個典型的體現(xiàn)接口作用的例子,之所以這么說是因為我想到有些朋友可能不太明白接口的好處,不太明白接口好處的朋友可以重點看一下這個例子,多多理解。
總結(jié)起來,回調(diào)的核心就是回調(diào)方將本身即this傳遞給調(diào)用方,這樣調(diào)用方就可以在調(diào)用完畢之后告訴回調(diào)方它想要知道的信息?;卣{(diào)是一種思想、是一種機制,至于具體如何實現(xiàn),如何通過代碼將回調(diào)實現(xiàn)得優(yōu)雅、實現(xiàn)得可擴展性比較高,一看開發(fā)者的個人水平,二看開發(fā)者對業(yè)務(wù)的理解程度。
同步回調(diào)與異步回調(diào)
上面的例子,可能有人會提出這樣的疑問:
這個例子需要用什么回調(diào)啊,使用同步調(diào)用的方式,學(xué)生對象回答完畢問題之后直接把回答的答案返回給老師對象不就好了?
這個問題的提出沒有任何問題,可以從兩個角度去理解這個問題。
首先,老師不僅僅想要得到學(xué)生的答案怎么辦?可能這個老師是個更喜歡聽學(xué)生解題思路的老師,在得到學(xué)生的答案之前,老師更想先知道學(xué)生姓名和學(xué)生的解題思路,當然有些人可以說,那我可以定義一個對象,里面加上學(xué)生的姓名和解題思路不就好了。這個說法在我看來有兩個問題:
(1)如果老師想要的數(shù)據(jù)越來越多,那么返回的對象得越來越大,而使用回調(diào)則可以進行數(shù)據(jù)分離,將一批數(shù)據(jù)放在回調(diào)方法中進行處理,至于哪些數(shù)據(jù)依具體業(yè)務(wù)而定,如果需要增加返回參數(shù),直接在回調(diào)方法中增加即可
(2)無法解決老師希望得到學(xué)生姓名、學(xué)生解題思路先于學(xué)生回答的答案的問題
因此我認為簡單的返回某個結(jié)果確實沒有必要使用回調(diào)而可以直接使用同步調(diào)用,但是如果有多種數(shù)據(jù)需要處理且數(shù)據(jù)有主次之分,使用回調(diào)會是一種更加合適的選擇,優(yōu)先處理的數(shù)據(jù)放在回調(diào)方法中先處理掉。
另外一個理解的角度則更加重要,就是標題說的同步回調(diào)和異步回調(diào)了。例子是一個同步回調(diào)的例子,意思是老師向Ricky問問題,Ricky給出答案,老師問下一個同學(xué),得到答案之后繼續(xù)問下一個同學(xué),這是一種正常的場景,但是如果我把場景改一下:
老師并不想One-By-One這樣提問,而是同時向Ricky、Mike、Lucy、Bruce、Kate五位同學(xué)提問,讓同學(xué)們自己思考,哪位同學(xué)思考好了就直接告訴老師答案即可。
這種場景相當于是說,同學(xué)思考完畢完畢問題要有一個辦法告訴老師,有兩個解決方案:
(1)使用Future+Callable的方式,等待異步線程執(zhí)行結(jié)果,這相當于就是同步調(diào)用的一種變種,因為其本質(zhì)還是方法返回一個結(jié)果,即學(xué)生的回答
(2)使用異步回調(diào),同學(xué)回答完畢問題,調(diào)用回調(diào)接口方法告訴老師答案即可。由于老師對象被抽象成了Callback接口,因此這種做法的擴展性非常好,就像之前說的,即使老師換了換了一茬又一茬,對于同學(xué)來說,只關(guān)心的是調(diào)用Callback接口回傳必要的信息即可
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67895.html
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識點總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機制解讀抽象類與三大特征時間和時間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識點總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機制解讀抽象類與三大特征時間和時間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識點總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機制解讀抽象類與三大特征時間和時間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:在中,表示抽象的非阻塞異步執(zhí)行。在完成之后安排代碼的唯一方式是通過方法綁定回調(diào)函數(shù)。下圖描述了該示例的計算過程方法中綁定的回調(diào)函數(shù)只有當成功的時候才會調(diào)用。為了處理失敗的,需要通過綁定另一個回調(diào)函數(shù)。 介紹 ES7中,async/await 語法使異步promise的協(xié)調(diào)變得很簡單。如果你需要以特定順序異步獲取來自多個數(shù)據(jù)庫或API的數(shù)據(jù),可以使用雜亂的promise或回調(diào)函數(shù)。asy...
閱讀 1886·2021-11-12 10:36
閱讀 2324·2021-09-01 10:29
閱讀 2358·2019-08-30 15:56
閱讀 1026·2019-08-30 12:56
閱讀 2357·2019-08-26 13:58
閱讀 2278·2019-08-23 18:38
閱讀 1498·2019-08-23 18:32
閱讀 2114·2019-08-23 16:53