新聞中心
java 異步調(diào)用方法
asynchronous call(異步調(diào)用)
我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、烏蘇ssl等。為上千企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的烏蘇網(wǎng)站制作公司
一個(gè)可以無需等待被調(diào)用函數(shù)的返回值就讓操作繼續(xù)進(jìn)行的方法
中文名
異步調(diào)用
外文名
asynchronous call
領(lǐng)域
函數(shù)
杰作
線程
。
。
快速
導(dǎo)航
實(shí)戰(zhàn)用法異步調(diào)用使用方法
舉例
異步調(diào)用就是你 喊 你朋友吃飯 ,你朋友說知道了 ,待會(huì)忙完去找你 ,你就去做別的了。
同步調(diào)用就是你 喊 你朋友吃飯 ,你朋友在忙 ,你就一直在那等,等你朋友忙完了 ,你們一起去。
實(shí)戰(zhàn)用法
操作系統(tǒng)發(fā)展到今天已經(jīng)十分精巧,線程就是其中一個(gè)杰作。操作系統(tǒng)把 CPU 處理時(shí)間劃分成許多短暫時(shí)間片,在時(shí)間 T1 執(zhí)行一個(gè)線程的指令,到時(shí)間 T2又執(zhí)行下一線程的指令,各線程輪流執(zhí)行,結(jié)果好象是所有線程在并肩前進(jìn)。這樣,編程時(shí)可以創(chuàng)建多個(gè)線程,在同一期間執(zhí)行,各線程可以“并行”完成不同的任務(wù)。
在單線程方式下,計(jì)算機(jī)是一臺(tái)嚴(yán)格意義上的馮·諾依曼式機(jī)器,一段代碼調(diào)用另一段代碼時(shí),只能采用同步調(diào)用,必須等待這段代碼執(zhí)行完返回結(jié)果后,調(diào)用方才能繼續(xù)往下執(zhí)行。有了多線程的支持,可以采用異步調(diào)用,調(diào)用方和被調(diào)方可以屬于兩個(gè)不同的線程,調(diào)用方啟動(dòng)被調(diào)方線程后,不等對(duì)方返回結(jié)果就繼續(xù)執(zhí)行后續(xù)代碼。被調(diào)方執(zhí)行完畢后,通過某種手段通知調(diào)用方:結(jié)果已經(jīng)出來,請(qǐng)酌情處理。
java常見的幾種調(diào)用機(jī)制(同步調(diào)用,異步調(diào)用
1、同步調(diào)用
同步調(diào)用是最基本的調(diào)用方式,對(duì)象b中的方法直接調(diào)用對(duì)象a的方法,這個(gè)時(shí)候程序會(huì)等待對(duì)象a的方法執(zhí)行完返回結(jié)果之后才會(huì)繼續(xù)往下走。
代碼如下:
public class A {
public void methodA()
{
System.out.println("this is class A method");
}
}
public class B {
public void methodB()
{
A a = new A();
a.methodA();
System.out.println("this is class B method");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.methodB();
}
}
結(jié)果:
this is class A method
this is class B method
2、異步調(diào)用
對(duì)象b中的方法調(diào)用對(duì)象a的方法,程序并不需要等待對(duì)象a的方法返回結(jié)果值,直接繼續(xù)往下走。
代碼如下:
public class A extends Thread{
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("this is class A method");
}
}
public class B {
public void methodB()
{
A a = new A();
a.start();
System.out.println("this is class B method");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.methodB();
}
}
結(jié)果:
this is class B method
this is class A method
說明:異步調(diào)用我們通常采用多線程的方法來達(dá)到目的
3、回調(diào)
對(duì)象a的方法methodA()中調(diào)用對(duì)象b的methodB()方法,在對(duì)象b的methodB()方法中反過來調(diào)用對(duì)象a的callBack()方法,這個(gè)callBack()方法稱為回調(diào)函數(shù),這種調(diào)用方法稱為回調(diào)。
代碼如下:
public class A {
public void methodA()
{
B b = new B();
b.methodB(new A());
System.out.println("this is class A method : methodA");
}
public void callBack()
{
System.out.println("this is class A method : callBack");
}
}
public class B {
public void methodB(A a)
{
System.out.println("this is class B method : methodB");
a.callBack();
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
a.methodA();
}
}
運(yùn)行結(jié)果:
this is class B method : methodB
this is class A method : callBack
this is class A method : methodA
注意:這里如果為了代碼的擴(kuò)展性更好,可以把類A與類B抽象出一個(gè)接口出來,然后用實(shí)現(xiàn)類去實(shí)現(xiàn)著兩個(gè)接口,這樣代碼的擴(kuò)展性會(huì)更好,也能滿足更多的業(yè)務(wù)場(chǎng)景。
回調(diào)的核心在于:回調(diào)方將本身對(duì)象傳給調(diào)用方,調(diào)用方在本身代碼邏輯執(zhí)行完之后,調(diào)用回調(diào)方的回調(diào)方法。
如何用Java回調(diào)和線程實(shí)現(xiàn)異步調(diào)用
軟件模塊之間的調(diào)用關(guān)系可以分為兩大類:即同步調(diào)用和異步調(diào)用。在同步調(diào)用中,一段代碼(主調(diào)方)調(diào)用另一段代碼(被調(diào)方),主調(diào)方必須等待這段代碼執(zhí)行完成返回結(jié)果后,才能繼續(xù)往下執(zhí)行,所以,同步調(diào)用是一種阻塞式調(diào)用,主調(diào)方代碼一直阻塞等待直到被調(diào)方返回為止。同步調(diào)用相對(duì)比較直觀,也是大部分編程語言直接支持的一種調(diào)用方式。但是,同步調(diào)用在處理比較耗時(shí)的情況下會(huì)嚴(yán)重影響程序性能,影響人機(jī)交互的瞬時(shí)反應(yīng)。例如,某個(gè)程序需要訪問數(shù)據(jù)庫獲取大量數(shù)據(jù),然后根據(jù)這些數(shù)據(jù)進(jìn)行一系列處理,將處理結(jié)果顯示在程序主窗口。由于數(shù)據(jù)庫訪問和大量數(shù)據(jù)的處理都是耗時(shí)的工作,在這個(gè)工作完成之前,處理結(jié)果遲遲不能顯示,用戶點(diǎn)擊鼠標(biāo)也不會(huì)立即得到響應(yīng),讓用戶感到整個(gè)程序顯得很沉重。面對(duì)這樣一些需要比較長時(shí)間才能完成的應(yīng)用場(chǎng)景,我們需要采用一種非阻塞式調(diào)用方式,即異步調(diào)用方式。在異步調(diào)用中,主調(diào)方調(diào)用被調(diào)方后,不等待對(duì)方返回結(jié)果就繼續(xù)執(zhí)行后續(xù)代碼,被調(diào)方執(zhí)行完畢后,通過某種手段通知調(diào)用方:結(jié)果已經(jīng)出來,請(qǐng)酌情處理。我們可以對(duì)上面的例子改用異步調(diào)用將問題輕松化解:把整個(gè)耗時(shí)的工作放進(jìn)一個(gè)單獨(dú)的線程,由主調(diào)方啟動(dòng)此線程后繼續(xù)執(zhí)行后續(xù)代碼,線程在背后悄悄地處理費(fèi)時(shí)的工作,當(dāng)工作完成,采用回調(diào)的方式通知主調(diào)方工作完成,主調(diào)方將結(jié)果顯示在主窗口。經(jīng)過這樣的處理,主界面繼續(xù)進(jìn)行自己的工作而不必死等,就不會(huì)造成界面響應(yīng)遲鈍。
在實(shí)現(xiàn)異步調(diào)用機(jī)制時(shí),除了線程之外,還要用到回調(diào)。回調(diào)是一種雙向調(diào)用,也就是,被調(diào)方在被調(diào)用時(shí)也會(huì)調(diào)用主調(diào)方的代碼。在異步調(diào)用中,被調(diào)方需要在工作完成時(shí)通知主調(diào)方,即調(diào)用主調(diào)方的接口,這一機(jī)制通過回調(diào)實(shí)現(xiàn)。回調(diào)和異步調(diào)用的關(guān)系非常緊密,回調(diào)是異步調(diào)用的基礎(chǔ)[1]。
本文理論聯(lián)系實(shí)際,首先闡述如何使用Java實(shí)現(xiàn)回調(diào)機(jī)制,然后進(jìn)一步闡述使用Java回調(diào)和線程實(shí)現(xiàn)異步調(diào)用,最后,闡述在異步調(diào)用中如何處理超時(shí)問題。
1 Java回調(diào)機(jī)制的實(shí)現(xiàn)方法
實(shí)現(xiàn)Java回調(diào),需要做如下三件事情:
(1)定義一個(gè)回調(diào)接口CallbackInterface
接口中聲明回調(diào)方法handle,如圖1所示,回調(diào)方法就是一個(gè)普通的方法,接收一個(gè)消息字符串或者一個(gè)封裝了數(shù)據(jù)的事件。
(2)定義一個(gè)類實(shí)現(xiàn)回調(diào)接口
這個(gè)類其實(shí)就是消息接收者和處理者,也就是調(diào)用方,回調(diào)方法是消息發(fā)生時(shí)實(shí)際處理消息的方法,此處簡(jiǎn)化為一條打印語句。
(3)定義消息通知者
消息通知者也就是被調(diào)用方必須具備兩種能力,第一,它必須知道誰是消息接收者,第二,當(dāng)消息發(fā)生時(shí),它能夠回調(diào)這些接收者的回調(diào)方法。為了獲得這兩種能力,消息通知者首先必須提供一個(gè)注冊(cè)方法register, 通過注冊(cè)的方式來注冊(cè)多個(gè)對(duì)此消息或事件感興趣的對(duì)象。然后提供一個(gè)消息通知方法notifyMessage,在這個(gè)方法中調(diào)用所有消息接收者的回調(diào)方法。具體代碼如圖3所示。
比如用一個(gè)可變數(shù)組List用于保存消息接收者,注冊(cè)的過程實(shí)際上是將消息接收者添加到這個(gè)數(shù)組,以備在需要通知消息的時(shí)候調(diào)用這些消息接收者的回調(diào)方法。
使用Java回調(diào)和線程實(shí)現(xiàn)異步調(diào)用
線程是一個(gè)獨(dú)立的執(zhí)行流,其本質(zhì)是程序中一段并發(fā)執(zhí)行的代碼。在異步調(diào)用機(jī)制中引入線程,在線程中完成耗時(shí)的工作,其目的是讓調(diào)用方的主線程繼續(xù)執(zhí)行后續(xù)代碼而不需要等待被調(diào)方的結(jié)果返回。由于不需要等待,這樣我們就等于同時(shí)做了兩件事情,而這兩件事情分別是在不同的執(zhí)行流中執(zhí)行,主調(diào)者在當(dāng)前的主線程中執(zhí)行,被調(diào)者在另外一個(gè)線程中執(zhí)行,因此提高了程序的效率,避免了界面的響應(yīng)遲鈍。當(dāng)被調(diào)者執(zhí)行完成后,仍然采用回調(diào)通知主調(diào)者。
例如 LongTimeWorker是一個(gè)用于完成耗時(shí)工作的線程,同時(shí)又是消息通知者。其耗時(shí)工作在run方法中完成,另外提供一個(gè)注冊(cè)方法register, 和一個(gè)消息通知方法notifyMessage,在run方法的最后,即耗時(shí)工作完成以后,調(diào)用notifyMessage將消息廣播出去。
3 異步調(diào)用中超時(shí)問題的處理
異步調(diào)用通常都要加入超時(shí)機(jī)制,因?yàn)槲覀兛偸窍M谝粋€(gè)指定的時(shí)間范圍內(nèi)返回一個(gè)結(jié)果,即使沒有得到結(jié)果也該有個(gè)超時(shí)通知。這時(shí)我們需要使用“限時(shí)線程回調(diào)方式”,它在原有線程回調(diào)的基礎(chǔ)上加上一個(gè)計(jì)時(shí)器Timer以計(jì)算消耗的時(shí)間,如果時(shí)間期限到了任務(wù)還沒有執(zhí)行完成即中斷線程,并將超時(shí)消息廣播出去。LongTimeWorker類需要修改部分的代碼如圖8和圖9所示。
首先LongTimeWorker線程類增加了一個(gè)構(gòu)造方法,其參數(shù)是超時(shí)時(shí)間timeout,構(gòu)造方法的主要任務(wù)是創(chuàng)建一個(gè)定時(shí)器,每秒鐘計(jì)時(shí)一次,若超時(shí)時(shí)間到則終止本線程,并廣播超時(shí)消息。LongTimeWorker線程類的第二個(gè)改變發(fā)生在其run方法中,線程一啟動(dòng)立即開始計(jì)時(shí),完成工作后停止計(jì)時(shí),并廣播消息。
4 結(jié)束語
異步調(diào)用是一種非阻塞式調(diào)用方式,用于在處理比較耗時(shí)的任務(wù)時(shí)保證程序性能不受到影響。實(shí)現(xiàn)異步調(diào)用的關(guān)鍵在于要解決三個(gè)技術(shù)難題,它們分別是程序阻塞問題、異步消息的傳遞問題和超時(shí)問題。本文介紹的方法采用并發(fā)線程、回調(diào)機(jī)制和計(jì)時(shí)器使上述問題得到了圓滿解決。
當(dāng)前題目:java代碼使用異步調(diào)度 java 異步編程
分享URL:http://www.ef60e0e.cn/article/hgoseh.html