欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java回調(diào)機(jī)制解讀

 更新時(shí)間:2017年02月24日 08:36:31   作者:五月的倉頡  
本文主要介紹了Java回調(diào)機(jī)制的相關(guān)知識(shí),具有很好的參考價(jià)值,下面跟著小編一起來看下吧

模塊間調(diào)用

在一個(gè)應(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í)行時(shí)間不長的情況,因?yàn)閎()方法執(zhí)行時(shí)間一長或者直接阻塞的話,a()方法的余下代碼是無法執(zhí)行下去的,這樣會(huì)造成整個(gè)流程的阻塞。

(2)異步調(diào)用

異步調(diào)用是為了解決同步調(diào)用可能出現(xiàn)阻塞,導(dǎo)致整個(gè)流程卡住而產(chǎn)生的一種調(diào)用方式。類A的方法方法a()通過新起線程的方式調(diào)用類B的方法b(),代碼接著直接往下執(zhí)行,這樣無論方法b()執(zhí)行時(shí)間多久,都不會(huì)阻塞住方法a()的執(zhí)行。但是這種方式,由于方法a()不等待方法b()的執(zhí)行完成,在方法a()需要方法b()執(zhí)行結(jié)果的情況下(視具體業(yè)務(wù)而定,有些業(yè)務(wù)比如啟異步線程發(fā)個(gè)微信通知、刷新一個(gè)緩存這種就沒必要),必須通過一定的方式對(duì)方法b()的執(zhí)行結(jié)果進(jìn)行監(jiān)聽。在Java中,可以使用Future+Callable的方式做到這一點(diǎn)。

(3)回調(diào)

最后是回調(diào),回調(diào)的思想是:

  • 類A的a()方法調(diào)用類B的b()方法
  • 類B的b()方法執(zhí)行完畢主動(dòng)調(diào)用類A的callback()方法

這樣一種調(diào)用方式組成了上圖,也就是一種雙向的調(diào)用方式。

代碼示例

接下來看一下回調(diào)的代碼示例,代碼模擬的是這樣一種場景:老師問學(xué)生問題,學(xué)生思考完畢回答老師。

首先定義一個(gè)回調(diào)接口,只有一個(gè)方法tellAnswer(int answer),即學(xué)生思考完畢告訴老師答案:

/**
 * 回調(diào)接口,原文出處http://www.cnblogs.com/xrq730/p/6424471.html
 */
public interface Callback {
 public void tellAnswer(int answer);
}

定義一個(gè)老師對(duì)象,實(shí)現(xiàn)Callback接口:

/**
 * 老師對(duì)象,原文出處http://www.cnblogs.com/xrq730/p/6424471.html
 */
public class Teacher implements Callback {
 private Student student;
 public Teacher(Student student) {
 this.student = student;
 }
 public void askQuestion() {
 student.resolveQuestion(this);
 }
 @Override
 public void tellAnswer(int answer) {
 System.out.println("知道了,你的答案是" + answer);
 }
}

老師對(duì)象有兩個(gè)public方法:

(1)回調(diào)接口tellAnswer(int answer),即學(xué)生回答完畢問題之后,老師要做的事情

(2)問問題方法askQuestion(),即向?qū)W生問問題

接著定義一個(gè)學(xué)生接口,學(xué)生當(dāng)然是解決問題,但是接收一個(gè)Callback參數(shù),這樣學(xué)生就知道解決完畢問題向誰報(bào)告:

/**
 * 學(xué)生接口,原文出處http://www.cnblogs.com/xrq730/p/6424471.html
 */
public interface Student {
 public void resolveQuestion(Callback callback); 
}

最后定義一個(gè)具體的學(xué)生叫Ricky:

/**
 * 一個(gè)名叫Ricky的同學(xué)解決老師提出的問題,原文出處http://www.cnblogs.com/xrq730/p/6424471.html
 */
public class Ricky implements Student {
 @Override
 public void resolveQuestion(Callback callback) {
 // 模擬解決問題
 try {
  Thread.sleep(3000);
 } catch (InterruptedException e) {  
 }
 // 回調(diào),告訴老師作業(yè)寫了多久
 callback.tellAnswer(3);
 }
}

在解決完畢問題之后,第16行向老師報(bào)告答案。

寫一個(gè)測試類,比較簡單:

/**
 * 回調(diào)測試,原文出處http://www.cnblogs.com/xrq730/p/6424471.html
 */
public class CallbackTest {

 @Test
 public void testCallback() {
 Student student = new Ricky();
 Teacher teacher = new Teacher(student); 
 teacher.askQuestion(); 
 } 
}

代碼運(yùn)行結(jié)果就一行:

知道了,你的答案是3

簡單總結(jié)、分析一下這個(gè)例子就是:

(1)老師調(diào)用學(xué)生接口的方法resolveQuestion,向?qū)W生提問

(2)學(xué)生解決完畢問題之后調(diào)用老師的回調(diào)方法tellAnswer

這樣一套流程,構(gòu)成了一種雙向調(diào)用的關(guān)系。

代碼分析

分析一下上面的代碼,上面的代碼我這里做了兩層的抽象:

(1)將老師進(jìn)行抽象

將老師進(jìn)行抽象之后,對(duì)于學(xué)生來說,就不需要關(guān)心到底是哪位老師詢問我問題,只要我根據(jù)詢問的問題,得出答案,然后告訴提問的老師就可以了,即使老師換了一茬又一茬,對(duì)我學(xué)生而言都是沒有任何影響的

(2)將學(xué)生進(jìn)行抽象

將學(xué)生進(jìn)行抽象之后,對(duì)于老師這邊來說就非常靈活,因?yàn)槔蠋熚幢貙?duì)一個(gè)學(xué)生進(jìn)行提問,可能同時(shí)對(duì)Ricky、Jack、Lucy三個(gè)學(xué)生進(jìn)行提問,這樣就可以將成員變量Student改為List<Student>,這樣在提問的時(shí)候遍歷Student列表進(jìn)行提問,然后得到每個(gè)學(xué)生的回答即可

這個(gè)例子是一個(gè)典型的體現(xiàn)接口作用的例子,之所以這么說是因?yàn)槲蚁氲接行┡笥芽赡懿惶靼捉涌诘暮锰?,不太明白接口好處的朋友可以重點(diǎn)看一下這個(gè)例子,多多理解。

總結(jié)起來,回調(diào)的核心就是回調(diào)方將本身即this傳遞給調(diào)用方,這樣調(diào)用方就可以在調(diào)用完畢之后告訴回調(diào)方它想要知道的信息?;卣{(diào)是一種思想、是一種機(jī)制,至于具體如何實(shí)現(xiàn),如何通過代碼將回調(diào)實(shí)現(xiàn)得優(yōu)雅、實(shí)現(xiàn)得可擴(kuò)展性比較高,一看開發(fā)者的個(gè)人水平,二看開發(fā)者對(duì)業(yè)務(wù)的理解程度。

同步回調(diào)與異步回調(diào)

上面的例子,可能有人會(huì)提出這樣的疑問:

這個(gè)例子需要用什么回調(diào)啊,使用同步調(diào)用的方式,學(xué)生對(duì)象回答完畢問題之后直接把回答的答案返回給老師對(duì)象不就好了?

這個(gè)問題的提出沒有任何問題,可以從兩個(gè)角度去理解這個(gè)問題。

首先,老師不僅僅想要得到學(xué)生的答案怎么辦?可能這個(gè)老師是個(gè)更喜歡聽學(xué)生解題思路的老師,在得到學(xué)生的答案之前,老師更想先知道學(xué)生姓名和學(xué)生的解題思路,當(dāng)然有些人可以說,那我可以定義一個(gè)對(duì)象,里面加上學(xué)生的姓名和解題思路不就好了。這個(gè)說法在我看來有兩個(gè)問題:

(1)如果老師想要的數(shù)據(jù)越來越多,那么返回的對(duì)象得越來越大,而使用回調(diào)則可以進(jìn)行數(shù)據(jù)分離,將一批數(shù)據(jù)放在回調(diào)方法中進(jìn)行處理,至于哪些數(shù)據(jù)依具體業(yè)務(wù)而定,如果需要增加返回參數(shù),直接在回調(diào)方法中增加即可

(2)無法解決老師希望得到學(xué)生姓名、學(xué)生解題思路先于學(xué)生回答的答案的問題

因此我認(rèn)為簡單的返回某個(gè)結(jié)果確實(shí)沒有必要使用回調(diào)而可以直接使用同步調(diào)用,但是如果有多種數(shù)據(jù)需要處理且數(shù)據(jù)有主次之分,使用回調(diào)會(huì)是一種更加合適的選擇,優(yōu)先處理的數(shù)據(jù)放在回調(diào)方法中先處理掉。

另外一個(gè)理解的角度則更加重要,就是標(biāo)題說的同步回調(diào)和異步回調(diào)了。例子是一個(gè)同步回調(diào)的例子,意思是老師向Ricky問問題,Ricky給出答案,老師問下一個(gè)同學(xué),得到答案之后繼續(xù)問下一個(gè)同學(xué),這是一種正常的場景,但是如果我把場景改一下:

老師并不想One-By-One這樣提問,而是同時(shí)向Ricky、Mike、Lucy、Bruce、Kate五位同學(xué)提問,讓同學(xué)們自己思考,哪位同學(xué)思考好了就直接告訴老師答案即可。

這種場景相當(dāng)于是說,同學(xué)思考完畢完畢問題要有一個(gè)辦法告訴老師,有兩個(gè)解決方案:

(1)使用Future+Callable的方式,等待異步線程執(zhí)行結(jié)果,這相當(dāng)于就是同步調(diào)用的一種變種,因?yàn)槠浔举|(zhì)還是方法返回一個(gè)結(jié)果,即學(xué)生的回答

(2)使用異步回調(diào),同學(xué)回答完畢問題,調(diào)用回調(diào)接口方法告訴老師答案即可。由于老師對(duì)象被抽象成了Callback接口,因此這種做法的擴(kuò)展性非常好,就像之前說的,即使老師換了換了一茬又一茬,對(duì)于同學(xué)來說,只關(guān)心的是調(diào)用Callback接口回傳必要的信息即可

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • 關(guān)于idea更新到2020.2.3無法創(chuàng)建web項(xiàng)目原因 library is not specified

    關(guān)于idea更新到2020.2.3無法創(chuàng)建web項(xiàng)目原因 library is not specified

    這篇文章主要介紹了關(guān)于idea更新到2020.2.3無法創(chuàng)建web項(xiàng)目原因 library is not specified,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java Spring @Lazy延遲注入源碼案例詳解

    Java Spring @Lazy延遲注入源碼案例詳解

    這篇文章主要介紹了Java Spring @Lazy延遲注入源碼案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Java中List<T>和List<?>的區(qū)別詳解

    Java中List<T>和List<?>的區(qū)別詳解

    這篇文章主要介紹了Java中List<T>和List<?>的區(qū)別詳解。文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Maven搭建springboot項(xiàng)目的方法步驟

    Maven搭建springboot項(xiàng)目的方法步驟

    這篇文章主要介紹了Maven搭建springboot項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • SpringBoot整合gateway全過程

    SpringBoot整合gateway全過程

    這篇文章主要介紹了SpringBoot整合gateway全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 詳解如何判斷Java線程池任務(wù)已執(zhí)行完

    詳解如何判斷Java線程池任務(wù)已執(zhí)行完

    線程池的使用并不復(fù)雜,麻煩的是如何判斷線程池中的任務(wù)已經(jīng)全部執(zhí)行完了,所以接下來,我們就來看看如何判斷線程中的任務(wù)是否已經(jīng)全部執(zhí)行完吧
    2023-08-08
  • java反射使用示例分享

    java反射使用示例分享

    這篇文章主要介紹了java反射使用示例,代碼很簡單,需要的朋友可以參考下
    2014-02-02
  • SpringBoot整合ELK做日志超完整詳細(xì)教程

    SpringBoot整合ELK做日志超完整詳細(xì)教程

    本文詳細(xì)介紹了如何在springboot中快速接入ELK的過程,ELK可以說在實(shí)際項(xiàng)目中具有很好的適用價(jià)值,不管是小項(xiàng)目,還是中大型項(xiàng)目,都具備普適參考性,值得深入了解和學(xué)習(xí),感興趣的朋友一起看看吧
    2024-01-01
  • Java中ThreadLocal?導(dǎo)致內(nèi)存?OOM?的原因分析

    Java中ThreadLocal?導(dǎo)致內(nèi)存?OOM?的原因分析

    這篇文章主要介紹了Java中ThreadLocal導(dǎo)致內(nèi)存OOM的原因分析,文章基于Java的相關(guān)內(nèi)容展開ThreadLocal導(dǎo)致內(nèi)存OOM的原因分析,需要的小伙v阿布可以參考一下
    2022-05-05
  • Spring Cloud詳解實(shí)現(xiàn)聲明式微服務(wù)調(diào)用OpenFeign方法

    Spring Cloud詳解實(shí)現(xiàn)聲明式微服務(wù)調(diào)用OpenFeign方法

    這篇文章主要介紹了Spring Cloud實(shí)現(xiàn)聲明式微服務(wù)調(diào)用OpenFeign方法,OpenFeign 是 Spring Cloud 家族的一個(gè)成員, 它最核心的作用是為 HTTP 形式的 Rest API 提供了非常簡潔高效的 RPC 調(diào)用方式,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2022-07-07

最新評(píng)論